Các tập lệnh hook Git có thể được quản lý cùng với kho lưu trữ không?


334

Chúng tôi muốn tạo một vài tập lệnh hook cơ bản mà tất cả chúng ta có thể chia sẻ - cho những thứ như thông điệp cam kết định dạng trước. Git có các tập lệnh hook cho thường được lưu trữ bên dưới <project>/.git/hooks/. Tuy nhiên, các tập lệnh đó không được truyền bá khi mọi người thực hiện một bản sao và chúng không được kiểm soát phiên bản.

Có một cách tốt để giúp tất cả mọi người có được các kịch bản hook đúng? Tôi có thể làm cho các tập lệnh hook đó trỏ đến các tập lệnh được kiểm soát phiên bản trong repo của tôi không?


5
Một câu hỏi hay. Tôi chỉ muốn có một câu trả lời tốt hơn (không có khiếu nại với @mipadi, tôi chỉ ước git có cách để làm điều này theo cách tự động hơn - ngay cả khi chỉ với một tùy chọn được chỉ định để git clone.)
lindes

Tôi đồng ý, @lindes! Nhưng có lẽ hạn chế chia sẻ móc này trong cố ý? Mọi thứ sẽ trở nên lộn xộn cho người dùng Windows, tôi cho rằng.
kristianlm

@kristianlm: Có rất nhiều lý do khiến đôi khi nó trở nên lộn xộn ... và cũng có những lúc thật tuyệt khi có nó ở đó. Tôi chỉ muốn có một số tùy chọn hoặc một cái gì đó sẽ sao chép các hook. Tôi đoán đôi khi tôi sẽ phải kiểm tra mã git-core và tạo một bản vá. :) (Hoặc hy vọng rằng ai đó khác ... hoặc sống với cách giải quyết trong câu trả lời của mipadi , hoặc bất cứ điều gì.)
lindes

pre-commitlàm cho điều này dễ dàng cho móc trước cam kết. Không trả lời câu hỏi của OP về việc quản lý bất kỳ hook git tùy ý nào, nhưng hook pre-commit có lẽ được sử dụng thường xuyên nhất cho mục đích chất lượng mã.
ericsoco

Câu trả lời:


143

Về mặt lý thuyết, bạn có thể tạo một hooksthư mục (hoặc bất kỳ tên nào bạn thích) trong thư mục dự án của bạn với tất cả các tập lệnh, sau đó liên kết chúng vào .git/hooks. Tất nhiên, mỗi người nhân bản repo sẽ phải thiết lập các liên kết tượng trưng này (mặc dù bạn có thể thực sự ưa thích và có một kịch bản triển khai mà người nhân bản có thể chạy để thiết lập chúng bán tự động).

Để thực hiện liên kết tượng trưng trên * nix, tất cả những gì bạn cần làm là:

root="$(pwd)"
ln -s "$root/hooks" "$root/.git/hooks"

sử dụng ln -sfnếu bạn đã sẵn sàng ghi đè lên những gì trong.git/hooks


37
này là không tầm thường, vì vậy tôi bao gồm một liên kết như thế nào để liên kết mềm đúng cách: stackoverflow.com/questions/4592838/...
David T.

16
git phiên bản 2.9 hiện có tùy chọn cấu hình core.hooksPathđể thiết lập tệp bên ngoài .git để liên kết với thư mục hook.
Aaron Rabinowitz

213

Trong Git 2.9 , tùy chọn cấu hình core.hooksPathchỉ định thư mục hook tùy chỉnh.

Di chuyển hook của bạn đến một hooksthư mục theo dõi trong kho lưu trữ của bạn. Sau đó, định cấu hình từng phiên bản của kho lưu trữ để sử dụng theo dõi hooksthay vì $GIT_DIR/hooks:

git config core.hooksPath hooks

Nói chung, đường dẫn có thể là tuyệt đối hoặc liên quan đến thư mục nơi các hook được chạy (thường là gốc cây làm việc; xem phần MÔ TẢ man githooks).


15
... và thư mục hook để trỏ tới có thể là kho lưu trữ hook riêng biệt;)
René Link

10
Chà, thông số cấu hình này có tự động được đặt khi bạn thực hiện một bản sao git không?
Đổ chuông

4
Theo quy tắc, các biến cấu hình git không thể được đặt bởi kho lưu trữ mà bạn đang nhân bản. Tôi nghĩ rằng điều này là để ngăn chặn việc thực thi mã tùy ý. git config kiểm soát việc thực thi mã thông qua các hook, tên người dùng trên các thông điệp cam kết và các chức năng quan trọng khác.
Max Shenfield

1
Điều gì sẽ xảy ra nếu ai đó trong nhóm thực hiện kiểm tra git cho chi nhánh khác? Họ phải đưa nó vào mọi chi nhánh ..
jokerster

1
Đúng. Mặt khác, nếu bạn cập nhật các hook trong các xác nhận mới hơn, các repos được nhân bản sẽ tự động nhận được chúng khi làm việc trên các nhánh được xây dựng trên đỉnh của cam kết đó. Cả hai cách đều có những mặt trái và mặt trái của chúng.
fabb

15

Nếu dự án của bạn là một dự án JavaScript và bạn sử dụng npmnhư trình quản lý gói, bạn có thể sử dụng chia sẻ git-hook để thực thi githooks trên npm install.


5
Bây giờ tôi biết ai đang xâm nhập vào những thứ nhảm nhí đó .git/hooks.
gavenkoa

Cảnh báo - không hỗ trợ Windows (trừ khi nó chạy với tư cách quản trị viên trong git bash). Giải pháp đơn giản là thêm "cài đặt sẵn": "git config core.hooksPath hook" dưới dạng tập lệnh trong pack.json. tức là nơi hook là một thư mục chứa tập lệnh git của bạn.
Shane Gannon

8

Đối với người dùng Nodejs, một giải pháp đơn giản là cập nhật pack.json với

{
  "name": "name",
  "version": "0.0.1",
  ......
  "scripts": {
    "preinstall": "git config core.hooksPath hooks", 

Các cài đặt sẵn sẽ chạy trước

cài đặt npm

và chuyển hướng git để tìm kiếm các hook bên trong thư mục . \ hook (hoặc bất kỳ tên nào bạn chọn). Thư mục này sẽ bắt chước . \. Git \ hook về tên tệp (trừ .sample) và cấu trúc.

Hãy tưởng tượng Maven và các công cụ xây dựng khác sẽ có tương đương với cài đặt sẵn .

Nó cũng sẽ hoạt động trên tất cả các nền tảng.

Nếu bạn cần thêm thông tin, hãy xem https://www.viget.com/articles/two-ways-to-share-git-hooks-with-your-team/


5

Làm thế nào về git-hook , nó định tuyến .git/hooksvào tập lệnh trong thư mục dự án githooks.

Ngoài ra còn có rất nhiều tính năng để cho phép bạn giảm thiểu sao chép và móc liên kết ở khắp mọi nơi.


5

Hầu hết các ngôn ngữ lập trình hiện đại, hay đúng hơn là các công cụ xây dựng của chúng, đều hỗ trợ các plugin để quản lý các git hook. Điều đó có nghĩa là tất cả những gì bạn cần làm là định cấu hình gói.json, pom.xml, v.v. và bất kỳ ai trong nhóm của bạn sẽ không có tùy chọn nào ngoài việc tuân thủ trừ khi họ thay đổi tệp xây dựng. Plugin sẽ thêm nội dung vào thư mục .git cho bạn.

Ví dụ:

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

https://github.com/olukyrich/githook-maven-plugin

https://www.npmjs.com/package/git-hooks


Tôi đã cố gắng để đạt được điều đó một cách chung chung, để sử dụng trong các dự án của mình, vì vậy tôi đã viết công cụ này: pypi.org/project/hooks4git
Lovato

3

Chúng tôi đang sử dụng các giải pháp Visual Studio (và do đó là các dự án) có các sự kiện xây dựng trước và sau. Tôi đang thêm một dự án bổ sung có tên 'GitHookDeployer'. Dự án tự sửa đổi một tập tin trong sự kiện xây dựng bài. Tập tin đó được thiết lập để sao chép vào thư mục xây dựng. Do đó, dự án được xây dựng mọi lúc và không bao giờ được bỏ qua. Trong sự kiện xây dựng, nó cũng đảm bảo rằng tất cả các móc git được đặt đúng chỗ.

Lưu ý rằng đây không phải là một giải pháp chung, vì một số dự án, tất nhiên, không có gì để xây dựng.


1

Bạn có thể tạo thư mục hook của mình một kho lưu trữ git khác và liên kết nó dưới dạng một mô hình con ... Tôi đoán chỉ có giá trị nếu bạn có nhiều thành viên và hook thay đổi thường xuyên.


1

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


1

Lý tưởng nhất, hook được viết bằng bash, nếu bạn làm theo các tệp mẫu. Nhưng bạn có thể viết nó bằng bất kỳ ngôn ngữ nào có sẵn và chỉ cần đảm bảo rằng nó có cờ thực thi.

Vì vậy, bạn có thể viết mã Python hoặc Go để đạt được mục tiêu của mình và đặt nó dưới thư mục hook. Nó sẽ hoạt động, nhưng nó sẽ không được quản lý cùng với kho lưu trữ.

Hai lựa chọn

a) Đa tập lệnh

Bạn có thể mã hóa các hook của mình bên trong trợ giúp của bạn và thêm một đoạn mã nhỏ vào các hook để gọi tập lệnh hoàn hảo của bạn, như thế này:

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/myprecommit.js

b) Tập lệnh đơn

Một tùy chọn thú vị hơn là chỉ thêm một tập lệnh để thống trị tất cả, thay vì một tập lệnh. Vì vậy, bạn tạo một hook / mysuperhook.go và chỉ ra mọi hook mà bạn muốn có.

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/mysuperhook.go $(basename $0)

Tham số sẽ cung cấp tập lệnh của bạn mà hook đã được kích hoạt và bạn có thể phân biệt nó trong mã của mình. Tại sao? Đôi khi, bạn có thể muốn chạy cùng một kiểm tra cho cam kết và đẩy, chẳng hạn.

Và sau đó?

Sau đó, bạn có thể muốn có thêm các chức năng, như:

  • Kích hoạt móc thủ công để kiểm tra xem mọi thứ có ổn ngay cả trước khi cam kết hoặc đẩy. Nếu bạn chỉ gọi kịch bản của mình (tùy chọn a hoặc b) sẽ thực hiện thủ thuật.
  • Kích hoạt các hook trên CI, vì vậy bạn không cần phải viết lại các kiểm tra tương tự cho CI, ví dụ, đó chỉ là gọi các kích hoạt cam kết và đẩy. Giống như trên nên giải quyết nó.
  • Gọi các công cụ bên ngoài, như trình xác nhận đánh dấu hoặc trình xác nhận YAML. Bạn có thể tạo các tòa nhà chọc trời và cần xử lý STDOUT và STDERR.
  • Đảm bảo tất cả các nhà phát triển có một cách đơn giản để cài đặt các hook, do đó, một đoạn script đẹp cần được thêm vào kho lưu trữ để thay thế các hook mặc định bằng các hook chính xác
  • Có một số người trợ giúp toàn cầu, như kiểm tra để chặn các cam kết phát triển và làm chủ các nhánh, không phải thêm nó vào mọi kho lưu trữ. Bạn có thể giải quyết nó bằng cách có một kho lưu trữ khác với các tập lệnh toàn cầu.

Điều này có thể đơn giản hơn?

Có, có một số công cụ giúp bạn quản lý git-hook. Mỗi người trong số họ được thiết kế để giải quyết vấn đề từ một quan điểm khác nhau, và bạn có thể cần phải hiểu tất cả trong số họ để có được vấn đề tốt nhất cho bạn hoặc nhóm của bạn. GitHooks.com cung cấp rất nhiều đọc về hooking, và một số công cụ có sẵn ngày hôm nay.

Tính đến hôm nay, có 21 dự án được liệt kê ở đó với các chiến lược khác nhau để quản lý móc git. Một số chỉ làm điều đó cho một hook duy nhất, một số cho một ngôn ngữ cụ thể, v.v.

Một trong những công cụ đó, được viết bởi tôi và được cung cấp miễn phí dưới dạng một dự án mã nguồn mở, được gọi là hook4git . Nó được viết bằng Python (vì tôi thích nó) nhưng ý tưởng là xử lý tất cả các mục được liệt kê ở trên trong một tệp cấu hình duy nhất có tên .hooks4git.ini, nằm trong kho lưu trữ của bạn và có thể gọi bất kỳ tập lệnh nào bạn muốn gọi, bằng bất kỳ ngôn ngữ nào .

Sử dụng git hook là hoàn toàn tuyệt vời, nhưng cách chúng được cung cấp thường chỉ khiến mọi người tránh xa nó.


Tôi đã đăng một phiên bản rất ngắn trước đây và theo thỏa thuận với người điều hành, điều này mang đến lời giải thích bên trong nó và một liên kết ngắn gọn đến một công cụ mà tôi tự viết mà tôi nghĩ có thể giúp các nhà phát triển khác.
Lovato

1

Dành cho người dùng lớp

Tôi thấy các kịch bản này rất hữu ích cho các dự án gradle.

xây dựng. nâng cấp

apply from: rootProject.file('gradle/install-git-hooks.gradle')

gradle / install-git-hook.gradle

tasks.create(name: 'gitExecutableHooks') {
    doLast {
        Runtime.getRuntime().exec("chmod -R +x .git/hooks/");
    }
}
task installGitHooks(type: Copy) {
    from new File(rootProject.rootDir, 'pre-commit')
    into { new File(rootProject.rootDir, '.git/hooks') }
}
gitExecutableHooks.dependsOn installGitHooks
clean.dependsOn gitExecutableHooks

Cam kết trước

.... your pre commit scripts goes here
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.