Kait pra-dorong Git

115

Saya ingin menjalankan unit-test sebelum setiap git push dan jika tes gagal, batalkan push, tetapi saya bahkan tidak dapat menemukan hook pre-push, hanya ada pre-commit dan pre-rebase.

penjelajah domba
sumber

Jawaban:

14

Saya lebih suka menjalankan tes dalam hook pra-komitmen. Karena perubahan sudah dicatat saat melakukan. Dorong dan tarik hanya bertukar informasi tentang yang sudah direkam berubah. Jika sebuah tes gagal, Anda akan memiliki revisi yang "rusak" di repositori Anda. Apakah Anda sedang mendorongnya atau tidak.

ordnungswidrig
sumber
203
Saya umumnya setuju, meskipun jika Anda terbiasa membuat banyak komitmen tambahan untuk squash nanti, dan rangkaian pengujiannya besar, ini bisa jadi tidak praktis.
Kaskabel
Saya melihat. Jadi saya akan menyarankan tes dijalankan sebelum menggabungkan dengan cabang utama tetapi tidak ada hook pra-penggabungan juga. Namun ada hook "update" yang dapat digunakan untuk mencegah update ref di repositori jarak jauh: "Tepat sebelum memperbarui ref pada repositori jarak jauh, hook update dipanggil. Status keluarnya menentukan keberhasilan atau kegagalan ref update. Hook dijalankan sekali untuk setiap ref yang akan diperbarui, dan mengambil tiga parameter: nama ref yang diperbarui, nama objek lama yang disimpan di ref, dan nama objek baru yang akan disimpan di ref. "
ordnungswidrig
18
Turun memilih karena - meski informatif - itu sepenuhnya mengabaikan pertanyaan OP.
The Dembinski
1
@TheDembinski Saya tidak akan mengatakan bahwa itu mengabaikan pertanyaan OP. Bahkan itu mempertimbangkan dan mengatakan bahwa ada cara yang lebih baik untuk melakukannya daripada yang OP dalam pikirannya. Secara umum, itulah jenis jawaban yang ingin saya dapatkan.
calder.ty
9
@ calder.ty - Nah. manojlds lebih baik membahas apa yang penting. Faktanya, hook pra-komit yang menjalankan pengujian biasanya merupakan ide yang buruk. Ini mengasumsikan bahwa semua hal yang dilakukan harus lulus tes. Yang buruk untuk alur kerja umum yang berfokus pada kolaborasi. Jadi ya ... saya tidak setuju; ini bukan cara yang lebih baik untuk melakukan "itu" juga tidak menjawab pertanyaan.
The Dembinski
209

Git mendapat pre-pushkait di 1.8.2rilis.

Contoh pre-pushskrip: https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample

1.8.2 catatan rilis berbicara tentang pra-push hook baru: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt

manojlds
sumber
1
@manojlds tahukah Anda untuk apa pengait ini dirancang? Saya ingin menggunakannya untuk mendorong biner saya ke pelanggan saya saat mendorong ke cabang tertentu (yaitu membangun versi malam dan mengunggahnya dengan curl, sebelum mendorong). Masalahnya adalah butuh beberapa saat untuk membangun dan mengunggah, dan koneksi jarak jauh menutup. Jadi saya berakhir dengan biner saya dibangun dan diunggah ke pelanggan tetapi tidak didorong ke repo, karena repo jarak jauh menutup koneksi. Ada ide bagaimana menyiasatinya? Atau mungkin itu adalah ide yang buruk karena akarnya.
igrek
@igrek apakah Anda menemukan solusi untuk masalah penutupan koneksi?
Mario Estrada
1
@MarioEstrada, ya, saya tidak ingat persis bagaimana, tetapi saya membuatnya mendorong dua kali: perintah git pertama menjalankan tes unit dan kemudian jika tidak memutuskan sambungan itu mendorong dan memulai dorongan lain di utas lain, jika yang pertama mendorong kali keluar, yang kedua dari utas lain berfungsi untuk saya. Jika salah satu dari yang pertama dan kedua berhasil, yang pertama mendorong perubahan, dan yang kedua tidak mendorong apa pun. Triknya adalah saya menambahkan beberapa argumen, yang melewati pengujian unit (yang digunakan untuk git push kedua, jadi tidak memulai pengujian unit lagi)
igrek
24

Git mendapatkan hook pra-dorong di rilis 1.8.2.

Kait pra-dorong adalah apa yang saya butuhkan bersama dengan kait pra-komit. Selain melindungi cabang, mereka juga dapat memberikan keamanan ekstra yang dikombinasikan dengan kait pra-komit.

Dan untuk contoh tentang cara menggunakan (diambil dan diadopsi dan ditingkatkan dari entri yang bagus ini )

Contoh sederhana untuk login ke gelandangan, menjalankan tes dan kemudian push

#!/bin/bash
# Run the following command in the root of your project to install this pre-push hook:
# cp git-hooks/pre-push .git/hooks/pre-push; chmod 700 .git/hooks/pre-push

CMD="ssh [email protected] -i ~/.vagrant.d/insecure_private_key 'cd /vagrant/tests; /vagrant/vendor/bin/phpunit'"
protected_branch='master'

# Check if we actually have commits to push
commits=`git log @{u}..`
if [ -z "$commits" ]; then
    exit 0
fi

current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

if [[ $current_branch = $protected_branch ]]; then
    eval $CMD
    RESULT=$?
    if [ $RESULT -ne 0 ]; then
        echo "failed $CMD"
        exit 1
    fi
fi
exit 0

Seperti yang Anda lihat, contoh menggunakan cabang yang dilindungi, subjek kait pra-dorong.

Jimmy Kane
sumber
14

Jika Anda menggunakan baris perintah, cara termudah untuk melakukannya adalah dengan menulis skrip push yang menjalankan pengujian unit Anda dan, jika berhasil, menyelesaikan dorongan.

Sunting

Mulai git 1.8.2, jawaban ini sudah usang. Lihat jawaban manojlds di atas.

kubi
sumber
maksud Anda tidak menggunakan pengait sama sekali? cukup ganti "git pull" dengan, misalnya, "git uinttestspull"? bukan itu yang saya butuhkan
penjelajah domba
1
@sheepwalker: s / pull / push /, dan gunakan alias untuk membuatnya bagus dan pendek.
Cascabel
@sheepwalker Ya, bukan itu yang Anda minta, tapi seperti yang dikatakan @calmh, tidak ada kait pra-tekan.
kubi
8

Tidak ada hook untuk itu, karena push bukanlah operasi yang mengubah repositori Anda.

Anda dapat melakukan pemeriksaan di sisi penerima, di post-receivehook. Di situlah biasanya Anda akan menolak dorongan masuk. Menjalankan pengujian unit mungkin sedikit intensif untuk dilakukan, tetapi itu terserah Anda.

Jakob Borg
sumber
6

Sebagai catatan, ada patch ke Git 1.6 yang menambahkan hook pra-dorong . Saya tidak tahu apakah ini berfungsi terhadap 1.7.

Daripada mengacaukannya, Anda dapat menjalankan skrip push seperti yang direkomendasikan @kubi. Anda juga bisa menjadikannya sebagai tugas Rake sehingga ada di repo Anda. ruby-git bisa membantu dengan ini. Jika Anda memeriksa repo target, Anda dapat menjalankan pengujian hanya saat mendorong ke repo produksi.

Terakhir, Anda dapat menjalankan pengujian Anda di pre-commithook tetapi memeriksa cabang apa yang sedang dikomit. Kemudian Anda dapat memiliki, katakanlah, productioncabang yang mengharuskan semua tes lulus sebelum menerima komit tetapi Anda mastertidak peduli. limerick_rake mungkin berguna dalam skenario itu.

Turadg
sumber
terima kasih, sebenarnya saya sudah memilih varian terakhir (Akhirnya, Anda dapat menjalankan pengujian Anda di hook pra-commit Anda ..)
sheepwalker
1

The Script dihubungkan oleh yang sangat-sebagai jawabannya menunjukkan parameter dll untuk pre-pushkait ( $1nama terpencil, $2URL) dan cara mengakses komit (garis readdari stdin memiliki struktur <local ref> <local sha1> <remote ref> <remote sha1>)

#!/bin/sh

# An example hook script to verify what is about to be pushed.  Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed.  If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
#   <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).

remote="$1"
url="$2"

z40=0000000000000000000000000000000000000000

while read local_ref local_sha remote_ref remote_sha
do
    if [ "$local_sha" = $z40 ]
    then
        # Handle delete
        :
    else
        if [ "$remote_sha" = $z40 ]
        then
            # New branch, examine all commits
            range="$local_sha"
        else
            # Update to existing branch, examine new commits
            range="$remote_sha..$local_sha"
        fi

        # Check for WIP commit
        commit=`git rev-list -n 1 --grep '^WIP' "$range"`
        if [ -n "$commit" ]
        then
            echo >&2 "Found WIP commit in $local_ref, not pushing"
            exit 1
        fi
    fi
done

exit 0
serv-inc
sumber