次のようなロジックを実行するpre-receive フックを設定したかったのです。
- マージコミットがあるかどうかを確認します
- 新しいブランチがプッシュされたかどうかを確認します
- 複数のコミットがあるかどうかを確認します。
上記のいずれかが存在する場合は、ユーザーとやり取りして、変更をプッシュするかどうかを確認し、そうであれば変更をプッシュし、そうでない場合はドロップします。
gitの事前受信フックで上記を達成する可能性はありますか?
次のようなロジックを実行するpre-receive フックを設定したかったのです。
上記のいずれかが存在する場合は、ユーザーとやり取りして、変更をプッシュするかどうかを確認し、そうであれば変更をプッシュし、そうでない場合はドロップします。
gitの事前受信フックで上記を達成する可能性はありますか?
ユーザーが「ssh」を実行している他のマシンにいる可能性があり、標準入力がユーザーに送信されないため、少なくとも一般的には、 pre-receive フックでユーザーとやり取りすることはできません。(uid やユーザー名などを調べて、ユーザーを "コールバック" するスクリプトにエスケープすることで、何かを作り上げることができるかもしれません。その方向での実験はあなたに任せます。) これらすべてのチェックを行うことができます。 、 けれど。
pre-receive フックは (stdin で) 一連の行を取得します。
<old-value> SP <new-value> SP <ref-name> LF
(から引用githooks(5)
)。ref-name の形式が次の場合:
refs/heads/<branchname>
次に、指定されたブランチが作成、削除、または更新されています。<old-value>
400
秒の場合、ブランチが作成されています。<new-value>
400
秒の場合は削除されています。それ以外の場合は更新されています。(refs/heads/* 以外のものもあります。完全なリストについては、git-send-email フックを参照してください。)
ブランチが更新されている場合、 は<old-value>
それが指していたコミット ID であり、 は更新が許可されている場合に指し示すコミット ID です (これは pre-receive フックと<new-value>
update フックの両方に依存します)。
これは、2 番目と 3 番目のケース (および削除) を単純に検出するフックです。マージがあるかどうかを調べるには、各リビジョンを$between
調べて、マージ (つまり、複数の親がある) があるかどうかを確認する必要があります。コミットを停止するには、0 を返す代わりにゼロ以外で終了します。
#! /bin/sh
check()
{
local old=$1 new=$2 longref=$3
local between rev
if expr $old : '^00*$' >/dev/null; then
echo creating new branch ${longref#refs/heads/}
return 0
fi
if expr $new : '^00*$' >/dev/null; then
echo removing branch ${longref#refs/heads/}
return 0
fi
between=$(git rev-list $old..$new)
case "$between" in
*$'\n'*)
echo at least two revs
for rev in $between; do git log -1 --oneline $rev; done
return 0
esac
echo only one rev
return 0
}
while read old new longref; do
case $longref in
refs/heads/*) check $old $new $longref;;
esac
done
$between
(拒否する場合でも、リモートリポジトリに既に送信されている
ため、すべてのリビジョンを調べることができます)。
関数を変更 (および名前を変更) しましたcheck
。新しい名前である の下では、get_confirmation
デフォルトでプッシュを許可したくないケースを把握 (および 0 を返す) することを意図しています (許可する場合は 1 を返します)。
次に、メインループでこれを行うことができます:
case $longref in
refs/heads/*)
if get_confirmation $old $new $longref; then
case $PWD in
*.allow.git)
echo 'allowed via alternate path'
;;
*.git)
echo "denied ... push to ${PWD%.git}.allow.git to allow"
exit 1
;;
*)
echo "denied, don't know where I am"
exit 1
;;
esac
fi
;;
# add more cases here if desired
esac
--bare
これは、 に存在するクローンにプッシュすることを前提としています/some/path/to/repo.git
。
プッシュを許可する同等のリポジトリを作成するには、名前が で終わる実際の並列ディレクトリを作成する必要がありますrepo.allow.git
。HEAD
このディレクトリには、プレーン リポジトリからコピーされた1 つの実際のファイルが含まれている必要があります。ディレクトリ内の他のすべてのものは、へのシンボリックリンクにすることができます../repo.git/<same>
:
cd /some/path/to
mkdir repo.allow.git
cd repo.allow.git
ln -s ../repo.git/* .
rm HEAD; cp ../repo.git/HEAD .
HEAD
通常のファイルでなければならない理由は、そうでなければgit push
これを有効なレポとして扱わないからです (それがブランチへのリンクである場合にのみシンボリックリンクにすることが許可され、それがシンボリック参照を行う「古い方法」です) .
通常git push
は失敗し、代わりgit push remotehost:/some/path/to/repo.allow.git
にそれを通過させることができます。もちろん、あなたのユーザーは、このハッキングの目的全体を回避するために、常にそれを行う習慣を身につけるかもしれませんが、そうではないかもしれません。
もちろん、これはすべて、リモート リポジトリが Unix ライクなホストである (つまり、シンボリック リンクをサポートしている) ことを前提としています。