Menempatkan kait git ke dalam repositori

197

Apakah ini dianggap sebagai praktik yang buruk - untuk menempatkan .git / kait ke repositori proyek (menggunakan symlink, misalnya). Jika ya, apa cara terbaik untuk mengirimkan kait yang sama ke pengguna git yang berbeda?

shabunc
sumber

Jawaban:

143

Saya umumnya setuju dengan Scytale, dengan beberapa saran tambahan, cukup bahwa itu bernilai jawaban terpisah.

Pertama, Anda harus menulis skrip yang menciptakan symlink yang sesuai, terutama jika kaitan ini adalah tentang menegakkan kebijakan atau membuat pemberitahuan yang bermanfaat. Orang-orang akan lebih mungkin menggunakan kait jika mereka bisa mengetik bin/create-hook-symlinksdaripada jika harus melakukannya sendiri.

Kedua, menghubungkan kait secara langsung mencegah pengguna menambahkan kait pribadi mereka sendiri. Sebagai contoh, saya lebih suka contoh pre-commit hook yang memastikan saya tidak memiliki kesalahan spasi putih. Cara terbaik untuk melakukannya adalah dengan memasukkan skrip pembungkus kait ke dalam repo Anda, dan menghubungkan semua kait ke skrip tersebut. Wrapper kemudian dapat memeriksa $0(dengan asumsi itu adalah skrip bash; yang setara seperti argv[0]sebaliknya) untuk mengetahui hook mana yang dipanggil, kemudian memanggil hook yang sesuai dalam repo Anda, serta hook pengguna yang sesuai, yang harus diganti namanya , melewati semua argumen untuk masing-masing. Contoh cepat dari memori:

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

Skrip instalasi akan memindahkan semua kait yang sudah ada sebelumnya ke samping (tambahkan .localke nama mereka), dan menghubungkan semua nama kait yang dikenal ke skrip di atas:

#!/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
Cascabel
sumber
6
Saya menambahkan chmod +x .git/hooks/*Anda bin/create-hook-symlinks untuk mengerjakannya.
guneysus
6
@guneysus Anda seharusnya tidak memerlukannya, karena kait seharusnya sudah dapat dieksekusi (mereka harus diperiksa dengan cara itu) dan tautannya tidak memerlukan izin khusus, hanya file yang mereka tautkan.
Cascabel
13
Cara yang lebih baik untuk mendapatkan dir hook adalah HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks.
Arnold Daniels
2
Saya telah menyusun sistem sederhana berdasarkan ini untuk mengelola kait di proyek saya: ell.io/tt$Paws.js/blob/Master/Scripts/install-git-hooks.sh
ELLIOTTCABLE
6
Saya hanya mengambil hal-hal penting dan menaruhnya di repo github.com/sjungwirth/githooks
Scott Jungwirth
111

Tidak, memasukkan mereka ke dalam repositori baik-baik saja, saya bahkan menyarankan melakukannya (jika mereka juga berguna bagi orang lain). Pengguna harus mengaktifkannya secara eksplisit (seperti yang Anda katakan, misalnya dengan menghubungkan), yang pada satu sisi sedikit menyakitkan, tetapi melindungi pengguna di sisi lain dari menjalankan kode arbitrer tanpa persetujuan mereka.

scy
sumber
13
bagaimana jika itu adalah kebijakan perusahaan, maka kode tersebut tidak "sembarang" ini adalah kode yang diperlukan, jadi ini akan dianggap sebagai batasan dalam GIT, karena tidak memiliki direktori lain (pra-ditentukan), yang dilacak, yang juga mendapat dieksekusi bersama dengan kait biasa
Tobias Hagenbeek
14
Mengirim kait secara otomatis adalah masalah keamanan, saya senang Git tidak melakukannya secara langsung - untuk menegakkan kebijakan tim / perusahaan, menggunakan kait di sisi server atau membiarkan pengguna memutuskan secara manual untuk mengaktifkannya seperti yang dijelaskan @scy :)
Tandai K Cowan
4
"melindungi pengguna [...] dari menjalankan kode arbitrer tanpa persetujuan mereka". Jika pengembang mau melakukan seperti yang Anda sarankan (symlinking) maka hook dapat diubah oleh orang lain, dan jalankan "kode arbitrer tanpa persetujuan mereka"
MiniGod
24
MiniGod: Tentu saja. Jika Anda cukup paranoid, Anda bisa menyalin kait alih-alih menghubungkannya, lalu mengauditnya, dan hanya kemudian mengaktifkannya. Namun, sebagian besar (rujukan) repositori Git akan berisi kode sumber yang akan dijalankan pada mesin pengguna, jadi Anda cenderung menjalankan kode yang terus berubah, tidak diaudit. Tapi ya, Anda ada benarnya. ;)
scy
46

Saat ini Anda dapat melakukan hal berikut untuk menetapkan direktori yang berada di bawah kontrol versi menjadi direktori git kait Anda, misalnya, MY_REPO_DIR/.githooksakan

git config --local core.hooksPath .githooks/

Masih tidak dapat diberlakukan secara langsung tetapi, jika Anda menambahkan catatan di README Anda (atau apa pun), ini membutuhkan upaya minimal pada setiap bagian pengembang.

bbarker
sumber
3
Satu trik yang saya temukan di viget.com/articles/two-ways-to-share-git-hooks-with-your-team adalah mengatur opsi dari konfigurasi Makefile / CMake Anda / apa pun.
Julius Bullinger
6

Dari http://git-scm.com/docs/git-init#_template_directory , Anda dapat menggunakan salah satu dari mekanisme ini untuk memperbarui dir .git / hooks dari setiap repo git yang baru dibuat:

Direktori templat berisi file dan direktori yang akan disalin ke $ GIT_DIR setelah dibuat.

Direktori templat akan menjadi salah satu dari yang berikut ini (secara berurutan):

  • argumen yang diberikan dengan opsi --template;

  • isi dari variabel lingkungan $ GIT_TEMPLATE_DIR;

  • variabel konfigurasi init.templateDir; atau

  • direktori templat default: / usr / share / git-core / templates.

DavidN
sumber
5

Simpan di proyek dan instal di build

Seperti yang dinyatakan orang lain dalam jawaban mereka, Jika kait Anda spesifik untuk proyek-proyek tertentu, maka sertakan dalam proyek itu sendiri, yang dikelola oleh git. Saya akan mengambil ini lebih jauh dan mengatakan bahwa, mengingat itu adalah praktik yang baik untuk membangun proyek Anda menggunakan skrip atau perintah tunggal, kait Anda harus dipasang selama pembangunan.

Saya menulis artikel tentang mengelola kait git , jika Anda tertarik untuk membaca tentang ini lebih dalam lagi.

Java & Maven

Penafian penuh; Saya menulis plugin Maven yang dijelaskan di bawah ini.

Jika Anda menangani build management dengan Maven untuk proyek Java Anda, plugin Maven berikut ini menangani pemasangan kait dari lokasi di proyek Anda.

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

Masukkan semua kait Git Anda ke direktori di proyek Anda, lalu konfigurasikan Anda pom.xmluntuk menyertakan deklarasi, tujuan, dan konfigurasi plugin berikut.

<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>

Ketika Anda menjalankan proyek Anda, membangun plugin akan mengonfigurasi git untuk menjalankan hook dari direktori yang ditentukan. Ini akan secara efektif mengatur kait di direktori itu untuk semua orang yang mengerjakan proyek Anda.

JavaScript & NPM

Untuk NPM ada ketergantungan yang disebut Husky yang memungkinkan Anda untuk menginstal kait termasuk yang ditulis dalam JavaScript.

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

Lainnya

Selain itu, ada pra-komit untuk proyek Python, Overcommit untuk proyek Ruby, dan Lefthook untuk proyek Ruby atau Node.

Rudi Kershaw
sumber
1
Terima kasih telah membuat plugin ini, itu membuat mengintegrasikan file pra-komit saya menjadi sangat mudah.
Michiel Bugher
1

Inilah skrip, add-git-hook.sh, yang dapat Anda kirimkan sebagai file biasa di repositori dan dapat dieksekusi untuk menambahkan kait git ke file skrip. Sesuaikan kait mana yang akan digunakan (pra-komit, pasca-komit, pra-dorong, dll.) Dan definisi kait dalam heredoc kucing.

#!/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

Skrip ini mungkin masuk akal untuk memiliki izin yang dapat dieksekusi atau pengguna dapat menjalankannya secara langsung. Saya menggunakan ini untuk secara otomatis git-pull pada mesin lain setelah saya berkomitmen.

EDIT - Saya menjawab pertanyaan yang lebih mudah yang bukan apa yang diminta dan bukan apa yang dicari OP. Saya berpendapat tentang kasus penggunaan dan argumen untuk skrip pengiriman kait di repo versus mengelola mereka secara eksternal di komentar di bawah ini. Semoga itu lebih apa yang Anda cari.

pemandu matematika
sumber
Saya menghargai usaha Anda dan percaya ada informasi berharga di sini - itu tidak menjawab pertanyaan yang disebutkan.
shabunc
Menurut pendapat saya, jika kait khusus untuk repositori tertentu atau merupakan komponen integral dari alur kerja yang digunakan maka mereka termasuk dalam repositori sebagai file. Sulit untuk menempatkan mereka di tempat lain tanpa membuat lebih banyak masalah daripada memecahkannya. Anda dapat menyimpan kait umum dalam repositori miliknya sendiri atau pada drive bersama yang dapat menjaga repo proyek tetap bersih tetapi dengan biaya yang jauh lebih praktis. Saya setuju dengan pengguna lain dalam mengatakan bahwa kait harus mudah ditambahkan. Tautan simbolis dapat menciptakan ketergantungan yang tidak perlu pada sistem atau struktur file tertentu.
mathewguest
Selain itu, tautan simbolik mematahkan kemampuan pengguna untuk menambahkan kait mereka sendiri. Direktori .git / hooks tidak dilacak sehingga sumbernya harus dimulai dalam repositori dan membuatnya masuk ke skrip kait, bukan sebaliknya. Saya pikir argumen balasannya adalah bahwa kait git lebih terkait dengan alur kerja atau tim daripada proyek dan dengan demikian tidak termasuk dalam repositori. Bergantung pada case-use khusus Anda, apakah Anda lebih baik-baik saja dengan berpotensi mencemari repositori git dengan kaitan yang kurang terkait atau apakah Anda lebih suka melepaskan kerumitan dalam menempatkannya di tempat lain?
mathewguest
1

Untuk proyek-proyek PHP berbasis Komposer, Anda dapat secara otomatis mendistribusikan ke para insinyur. Berikut adalah contoh untuk kait pre-commit dan commit-msg.

Buat hooksfolder, lalu di composer.json Anda:

 },
 "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);\"",
     ],

Kemudian Anda bahkan dapat memperbaruinya saat proyek berlanjut karena semua orang berjalan composer installsecara teratur.

Elijah Lynn
sumber
0

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 mengganti semua kait Anda, tetapi mungkin membantu pengembang Anda dengan yang paling jelas tanpa konfigurasi neraka menginstal kait pada setiap komputer pengembang / repo.

Penafian: Saya adalah salah satu pendiri Datrees

Shimon Tolts
sumber
3
Saya pikir Anda membuat produk yang menarik tetapi saya juga berpikir ini tidak menjawab pertanyaan dan pada dasarnya adalah promosi diri dan tidak lebih.
shabunc