Bisakah skrip Git dikelola bersama dengan repositori?

337

Kami ingin membuat beberapa skrip kait dasar yang dapat kami bagikan bersama - untuk hal-hal seperti pra-pemformatan pesan komit. Git memiliki skrip kait untuk itu yang biasanya disimpan di bawah <project>/.git/hooks/. Namun, skrip tersebut tidak disebarkan ketika orang melakukan klon dan mereka tidak dikontrol versi.

Apakah ada cara yang baik untuk membantu semua orang mendapatkan skrip kait yang benar? Bisakah saya membuat skrip kait itu menunjuk ke skrip yang dikendalikan versi di repo saya?

Pat Notz
sumber
5
Pertanyaan yang bagus Saya hanya berharap ada jawaban yang lebih baik (tanpa keluhan ke @mipadi, saya hanya berharap git punya cara untuk melakukan ini dengan cara yang lebih otomatis - bahkan jika hanya dengan opsi yang ditentukan untuk git klon.)
lindes
Saya setuju, @lindes! Tapi mungkin membatasi berbagi kait ini dengan sengaja? Hal-hal akan menjadi berantakan bagi pengguna Windows, saya kira.
kristianlm
@ Kristianlm: Ada banyak alasan mengapa itu bisa berantakan di waktu-waktu tertentu ... dan juga saat-saat di sana ada baiknya. Saya hanya berharap ada beberapa opsi atau sesuatu yang akan menyalin kait. Saya kira saya harus memeriksa kode git-core kapan saja, dan membuat tambalan. :) (Atau berharap orang lain melakukannya ... atau hidup dengan solusi dalam jawaban mipadi , atau apa pun.)
lindes
pre-commitmembuatnya mudah untuk kait pra-komit. Tidak menjawab pertanyaan OP tentang mengelola sembarang git sewenang-wenang, tetapi kait pra-komit mungkin yang paling sering digunakan untuk tujuan kualitas kode.
ericsoco

Jawaban:

144

Secara teoritis, Anda dapat membuat hooksdirektori (atau nama apa pun yang Anda inginkan) di direktori proyek Anda dengan semua skrip, dan kemudian menghubungkannya .git/hooks. Tentu saja, setiap orang yang mengkloning repo harus mengatur symlinks ini (walaupun Anda bisa menjadi sangat mewah dan memiliki skrip deploy yang dapat dijalankan oleh cloner untuk mengaturnya secara semi-otomatis).

Untuk melakukan symlink pada * nix, yang perlu Anda lakukan adalah:

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

gunakan ln -sfjika Anda siap untuk menimpa apa yang ada di dalamnya.git/hooks

mipadi
sumber
38
ini non-sepele, jadi saya menyertakan tautan tentang cara menyinkronkan dengan benar: stackoverflow.com/questions/4592838/…
David T.
17
git versi 2.9 sekarang memiliki opsi konfigurasi untuk core.hooksPathmengatur file di luar .git untuk menautkan ke folder hooks.
Aaron Rabinowitz
216

Di Git 2.9 , opsi konfigurasi core.hooksPathmenentukan direktori kait kustom.

Pindahkan kait Anda ke hooksdirektori yang dilacak di repositori Anda. Kemudian, konfigurasikan setiap instance repositori untuk menggunakan yang dilacak hooksalih-alih $GIT_DIR/hooks:

git config core.hooksPath hooks

Secara umum, path mungkin absolut, atau relatif ke direktori tempat hook dijalankan (biasanya root tree yang berfungsi; lihat DESCRIPTION bagian dari man githooks).

Max Shenfield
sumber
15
... dan direktori hooks to point to dapat berupa repositori hooks terpisah;)
René Link
10
Nah, apakah parameter konfigurasi ini ditetapkan secara otomatis ketika Anda melakukan git clone?
Cincin
4
Sebagai aturan, variabel config git tidak dapat ditetapkan oleh repositori yang Anda kloning. Saya pikir ini untuk mencegah eksekusi kode arbitrer. git config mengontrol eksekusi kode melalui pengait, nama pengguna pada pesan komit, dan fungsi penting lainnya.
Max Shenfield
1
Bagaimana jika seseorang dalam tim melakukan git checkout ke cabang lain? Mereka harus memasukkannya di setiap cabang ..
jokerster
1
Itu benar. Di sisi lain, jika Anda memperbarui kait di komit yang lebih baru, repo yang dikloning akan secara otomatis mendapatkannya ketika bekerja pada cabang yang dibangun di atas komit itu. Kedua cara memiliki kelebihan dan kekurangannya.
Fabb
15

Jika proyek Anda adalah proyek JavaScript dan Anda gunakan npmsebagai pengelola paket, Anda dapat menggunakan shared-git-hooks untuk menjalankan githook npm install.

kilianc
sumber
5
Sekarang saya tahu siapa yang secara intrusi menambahkan omong kosong itu .git/hooks.
gavenkoa
Peringatan - tidak mendukung Windows (kecuali dijalankan sebagai admin di git bash). Solusi sederhana adalah menambahkan "preinstall": "git config core.hooksPath hooks" sebagai skrip di package.json. yaitu Where hooks adalah folder yang berisi skrip git Anda.
Shane Gannon
8

Untuk pengguna Nodejs solusi sederhana adalah memperbarui package.json dengan

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

Pra - instal akan berjalan sebelumnya

npm instal

dan arahkan kembali git untuk mencari kait di dalam direktori. \ hooks (atau nama apa pun yang Anda pilih). Direktori ini harus meniru . \. Git \ hooks dalam hal nama file (minus .sample) dan struktur.

Bayangkan Maven dan alat bangunan lainnya akan memiliki setara dengan pra - instal .

Ini juga harus bekerja di semua platform.

Jika Anda memerlukan info lebih lanjut, lihat https://www.viget.com/articles/two-ways-to-share-git-hooks-with-your-team/

Shane Gannon
sumber
5

Bagaimana dengan git-hooks , itu merutekan .git/hooksmemohon ke dalam skrip di bawah direktori proyek githooks.

Ada juga banyak fitur untuk memungkinkan Anda meminimalkan copy dan symlink hook di semua tempat.

cattail
sumber
5

Sebagian besar bahasa pemrograman modern, atau lebih tepatnya alat bangun mereka, mendukung plugin untuk mengelola kait git. Itu berarti semua yang perlu Anda lakukan adalah mengonfigurasi package.json, pom.xml, dll., Dan siapa pun di tim Anda tidak akan memiliki pilihan selain mematuhi kecuali mereka mengubah file build. Plugin akan menambahkan konten ke direktori .git untuk Anda.

Contoh:

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

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

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

yuranos
sumber
Saya mencoba mencapainya dengan cara yang umum, untuk digunakan dalam proyek-proyek saya, jadi saya menulis alat ini: pypi.org/project/hooks4git
Lovato
3

Kami menggunakan solusi Visual Studio (dan dengan demikian proyek) yang memiliki acara pra dan pasca pembuatan. Saya menambahkan proyek tambahan bernama 'GitHookDeployer'. Proyek sendiri memodifikasi file dalam acara post build. File itu diatur untuk disalin ke direktori build. Dengan demikian proyek ini dibangun setiap waktu dan tidak pernah dilewati. Dalam acara build, itu juga memastikan bahwa semua kait git ada di tempatnya.

Perhatikan bahwa ini bukan solusi umum, karena beberapa proyek, tentu saja, tidak punya apa-apa untuk dibangun.

Mike de Klerk
sumber
2

Anda dapat menggunakan solusi terkelola untuk manajemen kait pra-komitmen seperti pra-komitmen . Atau solusi terpusat untuk git-hook sisi-server seperti Datree.io . Ini memiliki kebijakan bawaan seperti:

  1. Mendeteksi dan mencegah penggabungan rahasia .
  2. Menegakkan konfigurasi pengguna Git yang tepat .
  3. Menegakkan integrasi tiket Jira - sebutkan nomor tiket di nama permintaan tarik / pesan komit.

Itu tidak akan menggantikan semua kait Anda, tetapi mungkin membantu pengembang Anda dengan yang paling jelas tanpa konfigurasi neraka menginstal kait pada setiap pengembang komputer / repo.

Penafian: Saya adalah salah satu pendiri Datrees

Shimon Tolts
sumber
1

Anda dapat membuat folder hook Anda sebagai repositori git lain dan menautkannya sebagai submodule ... Saya rasa itu hanya layak jika Anda memiliki banyak anggota dan hook berubah secara teratur.

Do-do-new
sumber
1

Idealnya, kait ditulis dalam bash, jika Anda mengikuti file sampel. Tetapi Anda dapat menulisnya dalam bahasa apa pun yang tersedia, dan pastikan bendera tersebut memiliki tanda executable.

Jadi, Anda dapat menulis kode Python atau Go untuk mencapai tujuan Anda, dan letakkan di bawah folder hooks. Ini akan berfungsi, tetapi tidak akan dikelola bersama dengan repositori.

Dua pilihan

a) Multi Script

Anda dapat memberi kode pada kait di dalam bantuan Anda, dan menambahkan sebagian kecil kode ke kait, untuk memanggil skrip sempurna Anda, seperti ini:

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

b) Naskah Tunggal

Opsi yang lebih keren adalah menambahkan hanya satu skrip untuk mengatur semuanya, bukan beberapa skrip. Jadi, Anda membuat kait / mysuperhook.go dan arahkan setiap kait yang Anda inginkan.

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

Parameter akan memberikan skrip yang dipicu oleh skrip Anda, dan Anda dapat membedakannya di dalam kode Anda. Mengapa? Kadang-kadang Anda mungkin ingin menjalankan cek yang sama untuk komit dan push, misalnya.

Lalu?

Kemudian, Anda mungkin ingin memiliki fungsionalitas lebih lanjut, seperti:

  • Trigger hook secara manual untuk memeriksa apakah semuanya baik-baik saja bahkan sebelum komit atau dorong. Jika Anda hanya memanggil skrip Anda (opsi a atau b) akan melakukan trik.
  • Trigger the hooks pada CI, jadi Anda tidak perlu menulis ulang cek yang sama untuk CI, itu hanya akan memanggil komit dan mendorong pemicu, misalnya. Sama seperti di atas harus menyelesaikannya.
  • Panggil alat eksternal, seperti validator penurunan harga, atau validator YAML. Anda dapat membuat syscalls dan perlu menangani STDOUT dan STDERR.
  • Pastikan semua pengembang memiliki cara sederhana untuk memasang kait, jadi skrip yang bagus perlu ditambahkan ke repositori untuk mengganti kait default dengan yang benar
  • Minta bantuan global, seperti cek untuk memblokir komit untuk mengembangkan dan menguasai cabang, tidak harus menambahkannya ke setiap repositori. Anda dapat menyelesaikannya dengan memiliki repositori lain dengan skrip global.

Bisakah ini lebih sederhana?

Ya, ada beberapa alat untuk membantu Anda mengelola git-hooks. Masing-masing dirancang untuk mengatasi masalah dari perspektif yang berbeda, dan Anda mungkin perlu memahami semuanya untuk mendapatkan yang terbaik untuk Anda atau tim Anda. GitHooks.com menawarkan banyak bacaan tentang mengait, dan beberapa alat tersedia saat ini.

Sampai hari ini, ada 21 proyek yang terdaftar di sana dengan berbagai strategi untuk mengelola kait git. Beberapa hanya melakukannya untuk satu kait, beberapa untuk bahasa tertentu, dan sebagainya.

Salah satu alat itu, yang ditulis oleh saya dan ditawarkan secara gratis sebagai proyek opensource, disebut hooks4git . Itu ditulis dalam Python (karena saya suka) tetapi idenya adalah untuk menangani semua item yang tercantum di atas dalam file konfigurasi tunggal bernama .hooks4git.ini, yang hidup di dalam repositori Anda dan dapat memanggil skrip apa pun yang ingin Anda panggil, dalam bahasa apa pun .

Menggunakan kait git benar-benar fantastis, tetapi cara mereka ditawarkan biasanya hanya membuat orang menjauh darinya.

Lovato
sumber
Saya telah memposting versi yang sangat singkat beberapa waktu lalu, dan sebagaimana disetujui oleh moderator, ini membawa penjelasan di dalamnya, dan tautan singkat ke alat yang saya tulis sendiri yang menurut saya dapat membantu pengembang lain.
Lovato
1

Untuk pengguna gradle

Saya menemukan skrip ini sangat berguna untuk proyek gradle.

build.gradle

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

gradle / install-git-hooks.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

pra-komit

.... your pre commit scripts goes here
a3765910
sumber