Móc đẩy trước Git


115

Tôi muốn chạy một bài kiểm tra đơn vị trước mỗi lần đẩy git và nếu các bài kiểm tra không thành công, hãy hủy lần đẩy, nhưng tôi thậm chí không thể tìm thấy móc đẩy trước, chỉ có pre-commit và pre-rebase.


Câu trả lời:


14

Tôi muốn chạy thử nghiệm trong một hook trước. Bởi vì sự thay đổi đã được ghi lại khi cam kết. Đẩy và kéo chỉ trao đổi thông tin về thay đổi đã được ghi lại. Nếu thử nghiệm không thành công, bạn đã có một bản sửa đổi "bị hỏng" trong kho lưu trữ của mình. Cho dù bạn đang đẩy nó hay không.


203
Tôi nói chung đồng ý, mặc dù nếu bạn có thói quen thực hiện nhiều cam kết gia tăng sau này và bộ thử nghiệm lớn, thì điều này có thể không thực tế.
Cascabel

Tôi hiểu rồi. Vì vậy, tôi sẽ đề xuất các bài kiểm tra chạy trước khi hợp nhất với nhánh chính nhưng không có móc nối trước hợp nhất. Tuy nhiên, có một hook "cập nhật" có thể được sử dụng để ngăn cập nhật ref trong kho lưu trữ từ xa: "Ngay trước khi cập nhật ref trên kho từ xa, update hook sẽ được gọi. Trạng thái thoát của nó quyết định sự thành công hay thất bại của ref update. hook thực thi một lần cho mỗi ref được cập nhật và nhận ba tham số: tên của ref đang được cập nhật, tên đối tượng cũ được lưu trữ trong ref và tên đối tượng mới sẽ được lưu trong ref. "
ordnungswidrig

18
Bỏ phiếu vì - trong khi có nhiều thông tin - nó hoàn toàn bỏ qua câu hỏi của OP.
Dembinski

1
@TheDembinski Tôi sẽ không nói rằng nó bỏ qua câu hỏi OP. Trên thực tế, nó đã xem xét và nói rằng có một cách tốt hơn để làm điều đó so với cách OP đã nghĩ. Đó nói chung là loại câu trả lời mà tôi muốn nhận được.
calder.ty

9
@ calder.ty - Không. manojlds giải quyết tốt hơn những gì quan trọng. Trên thực tế, các hook pre-commit chạy thử nghiệm thường là một ý tưởng tồi với imo. Nó giả định rằng tất cả những thứ được cam kết phải vượt qua các bài kiểm tra. Điều này không tốt cho quy trình công việc chung tập trung vào sự cộng tác. Vì vậy, yea ... Tôi không đồng ý; nó không phải là cách tốt hơn để làm "nó" và nó cũng không giải quyết câu hỏi.
Dembinski

209

Git có pre-pushmóc trong 1.8.2bản phát hành.

pre-pushTập lệnh mẫu : https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample

Ghi chú phát hành 1.8.2 nói về hook pre-push mới: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt


1
@manojlds bạn có biết cái móc này được thiết kế để làm gì không? Tôi muốn sử dụng nó để đẩy tệp nhị phân của mình cho khách hàng khi đẩy đến một chi nhánh cụ thể (tức là xây dựng phiên bản hàng đêm và tải lên với curl, trước khi đẩy). Vấn đề là phải mất một thời gian để xây dựng và tải lên, đồng thời kết nối từ xa sẽ đóng. Vì vậy, tôi kết thúc với tệp nhị phân của tôi được xây dựng và tải lên cho khách hàng nhưng không được đẩy lên một repo, vì repo từ xa đóng kết nối. Bất kỳ ý tưởng làm thế nào để giải quyết vấn đề này? Hoặc có thể nó là một ý tưởng tồi trong root của nó.
igrek

@igrek bạn đã tìm thấy giải pháp cho vấn đề đóng kết nối chưa?
Mario Estrada

1
@MarioEstrada, vâng, tôi không nhớ chính xác bằng cách nào, nhưng tôi đã thực hiện đẩy nó hai lần: lệnh git đầu tiên chạy các bài kiểm tra đơn vị và sau đó nếu nó không ngắt kết nối, nó sẽ đẩy và bắt đầu một lần đẩy khác trong một luồng khác, nếu lần đẩy đầu tiên ra, cái thứ hai từ một chủ đề khác phù hợp với tôi. Nếu lần đầu tiên và lần thứ hai thành công, thì lần đẩy đầu tiên thay đổi và lần đẩy thứ hai không có gì. Bí quyết là rằng tôi đã có một số tranh luận thêm, mà bỏ qua kiểm tra đơn vị (được sử dụng cho git push thứ hai, vì vậy nó đã không bắt đầu kiểm tra đơn vị một lần nữa)
igrek

24

Git có móc đẩy trước trong bản phát hành 1.8.2.

Móc đẩy trước là những gì tôi cần cùng với móc cam kết trước. Ngoài việc bảo vệ một chi nhánh, họ cũng có thể cung cấp bảo mật bổ sung kết hợp với các móc cam kết trước.

Và ví dụ về cách sử dụng (được lấy và thông qua và nâng cao từ mục nhập tốt đẹp này )

Ví dụ đơn giản để đăng nhập vào vagrant, chạy thử nghiệm và sau đó đẩy

#!/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 vagrant@192.168.33.10 -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

Như bạn có thể thấy ví dụ sử dụng một nhánh được bảo vệ, chủ đề của móc đẩy trước.


14

Nếu bạn đang sử dụng dòng lệnh, cách dễ nhất để làm điều này là viết một kịch bản đẩy chạy các bài kiểm tra đơn vị của bạn và nếu chúng thành công, hãy hoàn thành quá trình đẩy.

Biên tập

Kể từ git 1.8.2, câu trả lời này đã lỗi thời. Xem câu trả lời của manojlds ở trên.


ý bạn là không sử dụng móc gì cả? chỉ cần thay thế "git pull" bằng, ví dụ: "git uinttestspull"? đó là không chính xác những gì tôi cần
sheepwalker

1
@sheepwalker: s / pull / push / và sử dụng một bí danh để làm cho nó đẹp và ngắn gọn.
Cascabel

@sheepwalker Vâng, đó không phải là chính xác những gì bạn yêu cầu, nhưng như @calmh đã nói, không có móc đẩy trước.
kubi

8

Không có móc cho nó, bởi vì push không phải là một hoạt động sửa đổi kho lưu trữ của bạn.

Tuy nhiên, bạn có thể thực hiện kiểm tra ở phía nhận, trong post-receivehook. Đó là nơi bạn thường từ chối một cú hích đến. Chạy các bài kiểm tra đơn vị có thể hơi chuyên sâu để thực hiện một cách hiệu quả, nhưng điều đó tùy thuộc vào bạn.


6

Đối với bản ghi, có một bản vá cho Git 1.6 bổ sung thêm móc đẩy trước . Tôi không biết liệu nó có hoạt động với 1.7 hay không.

Thay vì rắc rối với điều đó, bạn có thể chạy tập lệnh đẩy như @kubi được đề xuất. Thay vào đó, bạn cũng có thể đặt nó thành tác vụ Rake để nó nằm trong repo của bạn. ruby-git có thể giúp bạn với điều này. Nếu bạn kiểm tra repo mục tiêu, bạn chỉ có thể chạy thử nghiệm khi chuyển sang repo sản xuất.

Cuối cùng, bạn có thể chạy các bài kiểm tra trong pre-commithook của mình nhưng hãy kiểm tra xem nhánh nào đang được cam kết. Sau đó, bạn có thể có, chẳng hạn, một productionnhánh yêu cầu tất cả các bài kiểm tra phải vượt qua trước khi chấp nhận một cam kết nhưng bạn masterkhông quan tâm. Lemonrick_rake có thể hữu ích trong trường hợp đó.


cảm ơn, thực sự tôi đã chọn các biến thể cuối cùng (Cuối cùng, bạn có thể chạy thử nghiệm của bạn trong pre-cam kết nối của bạn ..)
sheepwalker

1

Tập lệnh được liên kết bởi câu trả lời được bình chọn cao hiển thị các tham số, v.v. cho pre-pushhook ( $1là tên từ xa, $2URL) và cách truy cập các cam kết (các dòng readtừ stdin có cấu trúc <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
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.