특정 분기를 처리하기 위해 git post-receive 후크 작성


107

다음은 회사 서버에있는 베어 저장소의 현재 후크입니다. git push origin master 이 후크는 Assembla로 푸시됩니다. 내가 필요한 것은 누군가가 우리 서버의 해당 분기에 변경 사항을 푸시 할 때 하나의 분기 (이상적으로는 마스터) 만 푸시하고 다른 분기에 대한 푸시는 무시하는 것입니다. 베어 저장소에서 분기를 선택하고 해당 분기 만 Assembla로 푸시 할 수 있습니까?


무슨 말이야? 내가 Assembla로 정의되었다고 가정 하는 원격으로 분기를 git push origin master푸시합니다 . 누군가가 , 반대로 , 또는 이와 비슷한 것을 눌렀을 때만 훅 을 트리거 해야 한다는 말입니까? masteroriginmasterfeature1
Stefan Kendall

@Stefan 정확합니다. 단어를 찾을 수 없었습니다, 헤헤.
Jorge Guberte 2011 년

답변:


386

수신 후 후크는 형식으로 stdin에서 인수를 가져옵니다 <oldrev> <newrev> <refname>. 이러한 인수가없는 명령 행 인수에서 표준 입력에서 오는 때문에, 당신은 사용할 필요가 read대신 $1 $2 $3.

포스트받을 후크가 한 번에 여러 가지를받을 수 있습니다 (누군가를 않는 경우, 예를 들어 git push --all), 우리는 또한 포장 할 필요가 있으므로 readA의 while루프.

작동하는 스 니펫은 다음과 같습니다.

#!/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
"=="는 나를 위해 작동하지 않습니다. 단일 "="를 사용하면 잘 작동합니다.
Ray

1
오래된 스레드를 불러 와서 미안하지만 if 문에서 오류가 발생합니다. 치명적 : 원격 끝이 예기치 않게 끊겼습니다. 오류 : 측 파대 디멀티플렉서에 오류가 있습니다. if 문 외부에서 $ branch를 에코합니다.
gin93r 2014

5
@ 레이, #!/bin/sh대신 #!/bin/bash있습니까?
shuttle87

2
내가 생각할 수있는 한 가지 위험은 태그가 브랜치 이름과 겹칠 수 있기 때문입니다. refs/heads/master대신 찾는다면 refs/tags/master괜찮을 것입니다. 그래도 생각할 수없는 이와 같은 다른 경우가있을 수 있습니다. 그 자체로 좋은 StackOverflow 질문이 될 수 있습니다.
pauljz

1
@pauljz 나는 if branch=$(git rev-parse --symbolic --abbrev-ref $refname 2>/dev/null); then분기를 제거 할 때 자식이 불평하지 않도록 사용 합니다.
Jérôme

8

수신 후 후크가 stdin에서 가져 오는 마지막 매개 변수는 ref가 변경된 것이므로 해당 값이 "refs / heads / master"인지 확인하는 데 사용할 수 있습니다. 수신 후 후크에서 사용하는 것과 비슷한 약간의 루비 :

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

푸시 된 각 참조에 대한 라인을 가져 오므로 마스터 이상을 푸시해도 여전히 작동합니다.


Ruby 예제에 감사드립니다. 나는 이와 비슷한 것을 할 것입니다.
Leif

6

Stefan의 대답은 나에게 효과가 없었지만 이것은 효과 가 있습니다.

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

간단한 이름 (마스터, 테스트 등)의 브랜치에서 나를 위해 일했지만 브랜치 이름이 있으면 prod12 / proj250 / ropesPatch12. 잘 작동하지 않습니다. 이러한 특수 문자로 작업 할 수있는 솔루션이 있습니까?
Shachar Hamuzim Rajuan 2015

3

위의 솔루션 중 어느 것도 저에게 효과적이지 않았습니다. 많은 디버깅 끝에 '읽기'명령을 사용하는 것이 작동하지 않는 것으로 나타났습니다. 대신 명령 줄 인수를 일반적인 방식으로 구문 분석하면 정상적으로 작동합니다.

다음은 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

업데이트 : 더 낯선 메모에서 pre-receive 후크는 stdin을 통해 입력을 받으므로 'read'로 읽습니다 (와우, 내가 그렇게 말할 줄은 몰랐습니다). 업데이트 후 후크는 여전히 $ 1에서 작동합니다.


2
가치가있는 경우 위의 솔루션은 post-receive후크가 아닌 post-update후크 전용이므로 작동하지 않았을 수 있습니다 . 그들은 다른 방식으로 입력을받습니다.
pauljz 2014

post-receive여기에 명시된대로 stdin을 사용합니다. git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
h4xnoodle

1

@pauljz의 답변은와 같은 특정 git 후크에 대해 잘 작동 pre-push하지만 pre-commit해당 변수에 대한 액세스 권한이 없습니다.oldrev newrev refname

그래서 저는 pre-commit 또는 실제로 작동하는 대체 버전을 만들었습니다. 이것은 우리가 브랜치 에 있지 않은 경우 스크립트 pre-commit를 실행 하는 후크입니다 .huskymaster

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

누군가에게 도움이되기를 바랍니다. 필요에 따라 iffi문 사이의 모든 것을 쉽게 수정할 수 있습니다 .


0

이 기능을 수행하기 위해 PHP 스크립트를 작성했습니다.

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

서버에서이 파일을 호스팅하고, 가급적 repo 루트를 호스트하고 github 웹훅에서 URL을 정의하십시오. 분기 이름으로 8 행의 'allcommits'를 변경하고 18 행에 코드 / 함수를 추가하십시오.

예 :

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.