特定のブランチを処理するgit post-receiveフックを作成する


107

git push origin master これが、会社のサーバーにあるベアリポジトリの現在のフック です。このフックは、Assemblaにプッシュします。私が必要なのは、誰かが変更をサーバーのブランチにプッシュしたときに1つのブランチ(マスター、理想的には)だけをプッシュし、他のブランチへのプッシュは無視することです。ベアリポジトリからブランチを選択し、そのブランチのみをAssemblaにプッシュすることは可能ですか?


どういう意味ですか?ブランチをリモートにgit push origin masterプッシュするだけです。これは、Assemblaとして定義されていると想定しています。誰かがにではなく、にプッシュしたときだけフックをトリガーする必要があると言っていますか?masteroriginmasterfeature1
Stefan Kendall

@Stefanその通りです。言葉が見つかりませんでした。
ホルヘギュベール

回答:


386

post-receiveフックは、その引数をの形式でstdinから取得します<oldrev> <newrev> <refname>。これらの引数はコマンドライン引数ではなくstdinから取得されるため、readではなくを使用する必要があります$1 $2 $3

フックは、(例えば、誰かがない場合は、一度に複数のブランチを受け取ることができますポスト受信git push --all)を、我々はまた、ラップする必要がありそうreadwhileループ。

実際のスニペットは次のようになります。

#!/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
「==」は機能しません。単一の「=」でうまくいきます。
レイ

1
古いスレッドを表示して申し訳ありませんが、ifステートメントでエラーが発生します。致命的:リモートエンドが突然ハングアップしました。error:サイドバンドデマルチプレクサーのエラー。これは、ifステートメントの外側の$ branchをエコーし​​ます。
gin93r 2014

5
@レイ、#!/bin/sh代わりに持っています#!/bin/bashか?
シャトル87

2
名前はブランチ名と重複する可能性があるので、私が考えることができる1つのリスクはタグです。refs/heads/master代わりに探す場合はrefs/tags/master大丈夫です。このような他のエッジケースがあるかもしれませんが、私は考えられません。それ自体がStackOverflowの良い質問になる可能性があります。
pauljz

1
@pauljz if branch=$(git rev-parse --symbolic --abbrev-ref $refname 2>/dev/null); thenブランチを削除したときにgitが文句を言わないようにしています。
ジェローム2018年

8

post-receiveフックが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

ステファンの答えは私にはうまくいきませんでしたが、これはうまくいきました:

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

単純な名前(master、testなど)のブランチで私のために働いたが、そのようなブランチ名を持っているとき:prod12 / proj250 / ropesPatch12。それはうまく機能しません。これらの特殊文字を処理できるソリューションはありますか?
Shachar Hamuzim Rajuan、2015

3

上記のいずれの解決策も私にとってはうまくいきませんでした。多くのデバッグを行った後、「read」コマンドを使用しても機能しないことがわかりました。代わりに、コマンドライン引数の解析は通常の方法でうまくいきます。

これが、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ここに記載されているように標準入力を取ります:git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
h4xnoodle

1

@pauljzからの答えは、のような特定のGitのフックの罰金に動作しますpre-pushが、pre-commitこれらの変数にアクセスすることはできません。oldrev newrev refname

それで、私はこの代替バージョンを作成しました。これは、プリコミット、または実際にはフックで機能します。これは、ブランチにいない場合にスクリプトpre-commitを実行するフックhuskyですmaster

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

このファイルをサーバー、できればレポルートでホストし、github webhooksで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.