Đưa móc git vào kho lưu trữ


197

Có phải nó được coi là một thực tiễn xấu - để đưa .git / hook vào kho dự án (ví dụ sử dụng symlink). Nếu có, cách tốt nhất để cung cấp cùng một hook cho những người dùng git khác nhau là gì?

Câu trả lời:


143

Tôi thường đồng ý với Scytale, với một vài gợi ý bổ sung, đủ để nó đáng để trả lời riêng.

Trước tiên, bạn nên viết một tập lệnh tạo ra các liên kết tượng trưng phù hợp, đặc biệt nếu các móc nối này là về thực thi chính sách hoặc tạo thông báo hữu ích. Mọi người sẽ có nhiều khả năng sử dụng móc hơn nếu họ chỉ có thể gõ bin/create-hook-symlinkshơn là họ phải tự làm.

Thứ hai, móc liên kết trực tiếp ngăn người dùng thêm vào móc cá nhân của riêng họ. Ví dụ, tôi thích hook hook pre-commit mẫu hơn, đảm bảo rằng tôi không có bất kỳ lỗi khoảng trắng nào. Một cách tuyệt vời để giải quyết vấn đề này là thả tập lệnh trình bao móc trong repo của bạn và liên kết tượng trưng tất cả các hook với nó. Sau đó, trình bao bọc có thể kiểm tra $0(giả sử đó là tập lệnh bash; tương tự như argv[0]cách khác) để tìm ra hook nào được gọi là, sau đó gọi hook thích hợp trong repo của bạn, cũng như hook của người dùng thích hợp, sẽ phải đổi tên , truyền tất cả các đối số cho mỗi. Ví dụ nhanh từ bộ nhớ:

#!/bin/bash
if [ -x $0.local ]; then
    $0.local "$@" || exit $?
fi
if [ -x tracked_hooks/$(basename $0) ]; then
    tracked_hooks/$(basename $0) "$@" || exit $?
fi

Tập lệnh cài đặt sẽ di chuyển tất cả các hook có sẵn sang một bên (nối .localvào tên của chúng) và symlink tất cả các tên hook đã biết đến tập lệnh trên:

#!/bin/bash
HOOK_NAMES="applypatch-msg pre-applypatch post-applypatch pre-commit prepare-commit-msg commit-msg post-commit pre-rebase post-checkout post-merge pre-receive update post-receive post-update pre-auto-gc"
# assuming the script is in a bin directory, one level into the repo
HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks

for hook in $HOOK_NAMES; do
    # If the hook already exists, is executable, and is not a symlink
    if [ ! -h $HOOK_DIR/$hook -a -x $HOOK_DIR/$hook ]; then
        mv $HOOK_DIR/$hook $HOOK_DIR/$hook.local
    fi
    # create the symlink, overwriting the file if it exists
    # probably the only way this would happen is if you're using an old version of git
    # -- back when the sample hooks were not executable, instead of being named ____.sample
    ln -s -f ../../bin/hooks-wrapper $HOOK_DIR/$hook
done

6
Tôi đã thêm chmod +x .git/hooks/*vào của bạn bin/create-hook-symlinks để làm việc đó.
guneysus

6
@guneysus Bạn không cần điều đó, bởi vì các hook nên đã được thực thi (chúng nên được kiểm tra theo cách đó) và các liên kết không cần bất kỳ quyền đặc biệt nào, chỉ các tệp mà chúng liên kết đến.
Cascabel

13
Một cách tốt hơn để có được các hook hook là HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks.
Arnold Daniels

2
Tôi đã kết hợp một hệ thống đơn giản dựa trên hệ thống này để quản lý các hook trong dự án của mình: ell.io/tt$Paws.js/blob/Master/Scripts/install-git-hooks.sh
ELLIOTTCABLE

6
Tôi chỉ lấy những thứ cần thiết và đặt nó trong một repo github.com/sjungwirth/githooks
Scott Jungwirth

111

Không, đưa chúng vào kho lưu trữ là tốt, tôi thậm chí còn đề nghị làm như vậy (nếu chúng cũng hữu ích cho người khác). Người dùng phải kích hoạt chúng một cách rõ ràng (ví dụ như bạn đã nói, bằng cách liên kết tượng trưng), một mặt hơi đau, nhưng mặt khác bảo vệ người dùng khỏi chạy mã tùy ý mà không có sự đồng ý của họ.


13
Điều gì xảy ra nếu đó là một điều chính sách của công ty, thì mã không phải là "tùy ý", đây là mã bắt buộc, vì vậy đây sẽ được coi là một hạn chế trong GIT, vì không có thư mục khác (được xác định trước), cũng được theo dõi, cũng được thực hiện cùng với các móc thông thường
Tobias Hagenbeek

14
Tự động phân phối hook là một vấn đề bảo mật, tôi rất vui vì Git không trực tiếp thực hiện - để thực thi chính sách nhóm / công ty, sử dụng hook ở phía máy chủ hoặc để người dùng quyết định kích hoạt chúng như @scy mô tả :)
Đánh dấu K Cowan

4
"Bảo vệ người dùng [...] khỏi chạy mã tùy ý mà không có sự đồng ý của họ". Nếu một nhà phát triển sẽ làm như bạn đề xuất (liên kết tượng trưng) thì người khác có thể thay đổi hook và chạy "mã tùy ý mà không có sự đồng ý của họ"
MiniGod

24
MiniGod: Tất nhiên rồi. Nếu bạn đủ hoang tưởng, bạn có thể sao chép các hook thay vì liên kết chúng, sau đó kiểm tra chúng và chỉ sau đó kích hoạt chúng. Tuy nhiên, hầu hết (cần dẫn nguồn) Kho lưu trữ Git sẽ chứa mã nguồn sẽ được chạy trên máy của người dùng, do đó bạn có thể sẽ chạy liên tục thay đổi, mã không được kiểm tra. Nhưng vâng, bạn đã có một điểm. ;)
scy

46

Ngày nay, bạn có thể thực hiện các thao tác sau để đặt thư mục nằm dưới sự kiểm soát phiên bản thành thư mục git hook của bạn, ví dụ: MY_REPO_DIR/.githookssẽ là

git config --local core.hooksPath .githooks/

Vẫn không thể thực thi trực tiếp, nhưng, nếu bạn thêm một ghi chú trong README (hoặc bất cứ điều gì), điều này đòi hỏi tối thiểu nỗ lực cho mỗi phần của nhà phát triển.


3
Một mẹo tôi tìm thấy trên viget.com/articles/two-ways-to-share-git-hooks-with-your-team là đặt tùy chọn từ cấu hình Makefile / CMake / bất cứ điều gì.
Julius Bullinger

6

Từ http://git-scm.com/docs/git-init#_template_directory , bạn có thể sử dụng một trong các cơ chế này để cập nhật thư mục .git / hook của mỗi repo git mới được tạo:

Thư mục mẫu chứa các tệp và thư mục sẽ được sao chép vào $ GIT_DIR sau khi được tạo.

Thư mục mẫu sẽ là một trong những thứ sau đây (theo thứ tự):

  • đối số được đưa ra với tùy chọn --template;

  • nội dung của biến môi trường $ GIT_TEMPLATE_DIR;

  • biến cấu hình init.templateDir; hoặc là

  • thư mục mẫu mặc định: / usr / share / git-core / samples.


5

Lưu trữ trong dự án và cài đặt trong bản dựng

Như những người khác nêu trong câu trả lời của họ, Nếu hook của bạn là cụ thể cho các dự án cụ thể của bạn thì hãy đưa chúng vào chính dự án, được quản lý bởi git. Tôi sẽ còn làm điều này hơn nữa và nói rằng, do thực tế tốt khi xây dựng dự án của bạn bằng cách sử dụng một tập lệnh hoặc lệnh, các hook của bạn sẽ được cài đặt trong quá trình xây dựng.

Tôi đã viết một bài viết về việc quản lý móc git , nếu bạn muốn đọc về điều này sâu hơn một chút.

Java và Maven

Từ chối trách nhiệm đầy đủ; Tôi đã viết plugin Maven được mô tả dưới đây.

Nếu bạn đang xử lý quản lý xây dựng với Maven cho các dự án Java của mình, thì plugin Maven sau đây xử lý các cài đặt hook từ một vị trí trong dự án của bạn.

https://github.com/rudikershaw/git-build-hook

Đặt tất cả các móc Git của bạn vào một thư mục trong dự án của bạn, sau đó định cấu hình của bạn pom.xmlđể bao gồm khai báo, mục tiêu và cấu hình plugin sau đây.

<build>
  <plugins>
    <plugin>
      <groupId>com.rudikershaw.gitbuildhook</groupId>
      <artifactId>git-build-hook-maven-plugin</artifactId>
      <configuration>
        <gitConfig>
          <!-- The location of the directory you are using to store the Git hooks in your project. -->
          <core.hooksPath>hooks-directory/</core.hooksPath>
        </gitConfig>
      </configuration>
      <executions>
        <execution>
          <goals>       
            <!-- Sets git config specified under configuration > gitConfig. -->
            <goal>configure</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
      <!-- ... etc ... -->
  </plugins>
</build>

Khi bạn chạy dự án xây dựng, plugin sẽ cấu hình git để chạy hook ra khỏi thư mục được chỉ định. Điều này sẽ thiết lập hiệu quả các hook trong thư mục đó cho mọi người làm việc trong dự án của bạn.

JavaScript và NPM

Đối với NPM, có một phụ thuộc được gọi là Husky , cho phép bạn cài đặt các hook bao gồm các hook được viết bằng JavaScript.

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "npm test",
      "pre-push": "npm test",
      "...": "..."
    }
  }
}

Khác

Ngoài ra, có các cam kết trước cho các dự án Python, Overcommit cho các dự án Ruby và Lefthook cho các dự án Ruby hoặc Node.


1
Cảm ơn vì đã tạo plugin này, nó giúp việc tích hợp tệp pre-commit của tôi trở nên cực kỳ dễ dàng.
Michiel Bugher


1

Đối với các dự án PHP dựa trên Trình soạn thảo, bạn có thể tự động phân phối cho các kỹ sư. Dưới đây là một ví dụ cho các hook hook trước và commit-messenger.

Tạo một hooksthư mục, sau đó trong composer.json của bạn:

 },
 "scripts": {
     "post-install-cmd": [
         "cp -r 'hooks/' '.git/hooks/'",
         "php -r \"copy('hooks/pre-commit', '.git/hooks/pre-commit');\"",
         "php -r \"copy('hooks/commit-msg', '.git/hooks/commit-msg');\"",
         "php -r \"chmod('.git/hooks/pre-commit', 0777);\"",
         "php -r \"chmod('.git/hooks/commit-msg', 0777);\"",
     ],

Sau đó, bạn thậm chí có thể cập nhật chúng khi dự án tiếp tục vì mọi người đang chạy composer installmột cách thường xuyên.


0

Đây là một tập lệnh, add-git-hook.sh, mà bạn có thể gửi như một tệp thông thường trong kho lưu trữ và có thể được thực thi để nối hook git vào tệp tập lệnh. Điều chỉnh móc nào sẽ sử dụng (pre-commit, post-commit, pre-push, v.v.) và định nghĩa của hook trong heredoc cat.

#!/usr/bin/bash
# Adds the git-hook described below. Appends to the hook file
# if it already exists or creates the file if it does not.
# Note: CWD must be inside target repository

HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks
HOOK_FILE="$HOOK_DIR"/post-commit

# Create script file if doesn't exist
if [ ! -e "$HOOK_FILE" ] ; then
        echo '#!/usr/bin/bash' >> "$HOOK_FILE"
        chmod 700 "$HOOK_FILE"
fi

# Append hook code into script
cat >> "$HOOK_FILE" <<EOF

########################################
# ... post-commit hook script here ... #
########################################

EOF

Kịch bản này có thể có ý nghĩa để có quyền thực thi hoặc người dùng có thể chạy nó trực tiếp. Tôi đã sử dụng điều này để tự động git-pull trên các máy khác sau khi tôi cam kết.

EDIT-- Tôi đã trả lời câu hỏi dễ hơn không phải là những gì được hỏi và không phải là những gì OP đang tìm kiếm. Tôi đã phản đối các trường hợp sử dụng và các đối số để vận chuyển các tập lệnh hook trong repo so với việc quản lý chúng bên ngoài trong các bình luận bên dưới. Hy vọng đó là nhiều hơn những gì bạn đang tìm kiếm.


Tôi đánh giá cao nỗ lực của bạn và tin rằng có một thông tin có giá trị ở đây tuy nhiên - nó không trả lời câu hỏi đã nêu.
shabunc

Theo tôi, nếu các hook dành riêng cho một kho lưu trữ cụ thể hoặc là các thành phần không thể thiếu của các quy trình công việc được sử dụng thì chúng thuộc về kho lưu trữ dưới dạng các tệp. Thật khó để đặt chúng ở bất cứ nơi nào khác mà không tạo ra nhiều vấn đề hơn nó giải quyết. Bạn có thể lưu trữ các hook chung trong kho lưu trữ của riêng nó hoặc trên một ổ đĩa chung, điều này có thể giữ cho repo dự án sạch sẽ nhưng với chi phí ít thực tế hơn nhiều. Tôi đồng ý với những người dùng khác khi nói rằng các hook phải dễ dàng để thêm. Liên kết tượng trưng có thể tạo ra sự phụ thuộc không cần thiết vào một hệ thống hoặc cấu trúc tệp cụ thể.
toán học

Ngoài ra, các liên kết tượng trưng phá vỡ khả năng của người dùng để thêm móc của riêng họ. Thư mục .git / hook không được theo dõi để nguồn sẽ bắt đầu trong kho lưu trữ và chuyển nó vào tập lệnh hook chứ không phải theo cách khác. Tôi nghĩ rằng đối số sẽ là các git hook có liên quan nhiều hơn đến quy trình làm việc hoặc nhóm hơn là dự án và do đó không thuộc về kho lưu trữ. Tùy thuộc vào trường hợp sử dụng cụ thể của bạn, bạn có ổn hơn với khả năng gây ô nhiễm kho lưu trữ git với các móc nối ít liên quan hơn hay bạn muốn từ bỏ một loạt các phức tạp trong việc đặt chúng ở một nơi khác?
toán học

0

Bạn có thể sử dụng giải pháp được quản lý để quản lý hook pre-commit như pre-commit . Hoặc một giải pháp tập trung cho git-hook phía máy chủ như Datree.io . Nó có các chính sách tích hợp như:

  1. Phát hiện và ngăn chặn sáp nhập bí mật .
  2. Thực thi cấu hình người dùng Git thích hợp .
  3. Thực thi tích hợp vé Jira - đề cập đến số vé trong tên yêu cầu kéo / thông báo cam kết.

Nó sẽ không thay thế tất cả các hook của bạn, nhưng nó có thể giúp các nhà phát triển của bạn có những hook rõ ràng nhất mà không cần cấu hình cài đặt hook trên mọi máy tính / repo của nhà phát triển.

Tuyên bố miễn trừ trách nhiệm: Tôi là một trong những người sáng lập Datrees


3
Tôi nghĩ rằng bạn đang tạo ra một sản phẩm thú vị nhưng tôi cũng nghĩ rằng điều này không trả lời câu hỏi và về cơ bản là tự quảng cáo và không có gì hơn.
shabunc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.