Viết một hook sau khi nhận git để xử lý một nhánh cụ thể


107

Đây là hook hiện tại của tôi trong repo trần nằm trong máy chủ của công ty: git push origin master hook này đẩy đến Assembla. Những gì tôi cần là chỉ đẩy một nhánh (lý tưởng là chính) khi ai đó đẩy các thay đổi đến nhánh đó trên máy chủ của chúng tôi và bỏ qua các lần đẩy sang các nhánh khác. Có thể chọn nhánh từ repo trần và chỉ đẩy nhánh đó đến Assembla không?


Ý anh là gì? git push origin mastersẽ chỉ đẩy masternhánh đến originđiều khiển từ xa, mà tôi giả sử được định nghĩa là Assembla. Có phải bạn đang nói rằng bạn chỉ cần kích hoạt móc câu khi có ai đó đẩy tới master, ngược lại feature1hoặc tương tự?
Stefan Kendall

@Stefan Chính xác là như vậy. Tôi không tìm thấy từ, hehe.
Jorge Guberte

Câu trả lời:


386

Một móc sau nhận nhận đối số của nó từ stdin, ở dạng <oldrev> <newrev> <refname>. Vì các đối số này đến từ stdin, không phải từ đối số dòng lệnh, bạn cần sử dụng readthay thế $1 $2 $3.

Móc hậu nhận có thể nhận được nhiều chi nhánh cùng một lúc (ví dụ nếu ai đó làm một git push --all), vì vậy chúng tôi cũng cần phải bọc readtrong một whilevòng lặp.

Đoạn mã đang hoạt động trông giống như sau:

#!/bin/bash
while read oldrev newrev refname
do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    if [ "master" = "$branch" ]; then
        # Do something
    fi
done

2
"==" không hoạt động với tôi. Với đơn "=" phù hợp với tôi.
Ray

1
Rất tiếc khi đưa ra một chuỗi cũ, nhưng tôi gặp lỗi ở câu lệnh if. chết người: đầu điều khiển từ xa bị treo đột ngột. error: lỗi trong bộ phân kênh dải bên. Nó sẽ lặp lại nhánh $ bên ngoài câu lệnh if.
gin93r

5
@Ray, bạn có #!/bin/shthay vì #!/bin/bash?
tàu con thoi 87

2
Một rủi ro mà tôi có thể nghĩ đến là các thẻ, vì tên của chúng có thể trùng với tên chi nhánh. Nếu bạn tìm kiếm refs/heads/masterthay vì refs/tags/masterbạn sẽ không sao. Có thể có những trường hợp phức tạp khác như thế này mà tôi không thể nghĩ đến. Nó có thể là một câu hỏi StackOverflow hay theo đúng nghĩa của nó.
pauljz

1
@pauljz Tôi sử dụng if branch=$(git rev-parse --symbolic --abbrev-ref $refname 2>/dev/null); thenđể git không phàn nàn khi tôi loại bỏ một nhánh.
Jérôme

8

Tham số cuối cùng mà hook post-nhận được trên stdin là ref đã được thay đổi, vì vậy chúng ta có thể sử dụng tham số đó để kiểm tra xem giá trị đó có phải là "refs / heads / master" hay không. Một chút ruby ​​tương tự như những gì tôi sử dụng trong móc sau khi nhận:

STDIN.each do |line|
    (old_rev, new_rev, ref_name) = line.split
    if ref_name =~ /master/
         # do your push
    end
end

Lưu ý rằng nó có một dòng cho mỗi ref đã được đẩy, vì vậy nếu bạn đẩy nhiều hơn chỉ master, nó vẫn hoạt động.


Cảm ơn về ví dụ Ruby. Tôi sẽ làm một cái gì đó tương tự như thế này.
Leif

6

Câu trả lời của Stefan không phù hợp với tôi, nhưng điều này đã làm được:

#!/bin/bash

echo "determining branch"

if ! [ -t 0 ]; then
  read -a ref
fi

IFS='/' read -ra REF <<< "${ref[2]}"
branch="${REF[2]}"

if [ "master" == "$branch" ]; then
  echo 'master was pushed'
fi

if [ "staging" == "$branch" ]; then
  echo 'staging was pushed'
fi

echo "done"

Làm việc cho tôi cho các nhánh có tên đơn giản (chính, thử nghiệm, v.v.), nhưng khi tôi có tên nhánh như: prod12 / proj250 / ropesPatch12. nó không hoạt động tốt. Bạn có giải pháp nào có thể làm việc với các ký tự đặc biệt đó không?
Shachar Hamuzim Rajuan

3

Cả hai giải pháp trên đều không hiệu quả với tôi. Sau nhiều lần gỡ lỗi, hóa ra là sử dụng lệnh 'read' không hoạt động - thay vào đó, phân tích cú pháp các đối số dòng lệnh theo cách thông thường hoạt động tốt.

Đây là hook chính xác sau cập nhật mà tôi vừa thử nghiệm thành công trên CentOS 6.3.

#!/bin/bash

echo "determining branch"

branch=`echo $1 | cut -d/ -f3`

if [ "master" == "$branch" ]; then
    echo "master branch selected"
fi

if [ "staging" == "$branch" ]; then
    echo "staging branch selected"
fi

exec git update-server-info

CẬP NHẬT: trên một lưu ý thậm chí còn lạ, móc nối nhận trước nhận đầu vào của nó qua stdin, do đó được đọc bằng 'read' (wow, chưa bao giờ tôi nghĩ rằng tôi sẽ nói như vậy). Móc sau cập nhật vẫn hoạt động với $ 1 đối với tôi.


2
Đối với những gì nó đáng giá, các giải pháp trên có thể không hoạt động vì chúng đặc biệt dành cho post-receivemóc, không phải post-updatemóc. Họ tiếp nhận đầu vào theo nhiều cách khác nhau.
pauljz

post-receivelấy stdin như đã lưu ý ở đây: git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
h4xnoodle 19/02/16

1

Câu trả lời từ @pauljz hoạt động tốt cho một số git hook như pre-push, nhưng pre-commitkhông có quyền truy cập vào các biến đóoldrev newrev refname

Vì vậy, tôi đã tạo phiên bản thay thế này hoạt động cho pre-commit, hoặc thực sự và hook. Đây là một pre-commithook sẽ chạy một huskyscript nếu chúng ta KHÔNG ở trên masternhánh.

#!/bin/bash
# git 'commit' does not have access to these variables: oldrev newrev refname
# So get the branch name off the head

branchPath=$(git symbolic-ref -q HEAD) # Something like refs/heads/myBranchName
branch=${branchPath##*/}      # Get text behind the last / of the branch path

echo "Head: $branchPath";
echo "Current Branch: $branch";

if [ "master" != "$branch" ]; then

   # If we're NOT on the Master branch, then Do something
   # Original Pre-push script from husky 0.14.3

   command_exists () {
     command -v "$1" >/dev/null 2>&1
   }

   has_hook_script () {
     [ -f package.json ] && cat package.json | grep -q "\"$1\"[[:space:]]*:"
   }

   cd "frontend" # change to your project directory, if .git is a level higher

   # Check if precommit script is defined, skip if not
   has_hook_script precommit || exit 0

   # Node standard installation
   export PATH="$PATH:/c/Program Files/nodejs"

   # Check that npm exists
   command_exists npm || {
     echo >&2 "husky > can't find npm in PATH, skipping precommit script in package.json"
     exit 0
   }

   # Export Git hook params
   export GIT_PARAMS="$*"

   # Run npm script
   echo "husky > npm run -s precommit (node `node -v`)"
   echo

   npm run -s precommit || {
     echo
     echo "husky > pre-commit hook failed (add --no-verify to bypass)"
     exit 1
   }
fi

Tôi hy vọng điều đó sẽ giúp ai đó. Bạn có thể dễ dàng sửa đổi theo nhu cầu của mình, bất kỳ điều gì ở giữaiffi câu lệnh và .


0

Tôi đã viết một tập lệnh PHP cho chính mình để thực hiện chức năng này.

https://github.com/fotuzlab/githubdump-php

Lưu trữ tệp này trên máy chủ của bạn, tốt nhất là repo root và xác định url trong github webhooks. Thay đổi 'allcommits' trên dòng 8 bằng tên chi nhánh của bạn và thêm mã / chức năng của bạn ở dòng 18.

ví dụ

function githubdump($payload_object) {
    // Write your code here.
    exec('git push origin master');
}

0

Cách tiếp cận đơn giản, bằng git hookvăn bản

read refname
echo $refname

Đơn giản - thêm thông tin về hệ thống nối liên kết tuyệt vời này

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.