質問: 実現したいことは、あるブランチで直接 `commit` することを禁止し、他のブランチからの `merge commit` のみを許すことです。例えば、 Gitflow で運用した時に `develop` ブランチへの直接 `commit` を禁止して、 `feature` や `release` ブランチなどからの `merge commit` だけを認めることを開発メンバに強要したいといったケースです。 コミット前にチェックするための仕掛けとして `pre-commit` フックを使うのが最も自然だと思うんですが、実行されたのが `commit` か `merge --no-ff` による `merge commit` かをフックスクリプト(hook scripts)の中で区別する手段ってあるんでしょうか? もしくは `pre-commit` フックを使わずに上記を実現する方法はあるんでしょうか?
回答: `pre-commit` フックを使用しない方法はちょっと分からないので,素直に `pre-commit` フックを使用した方法を示します. `develop` ブランチへの `commit` を禁止するには, `.git/hooks/pre-commit` を ``` #!/bin/sh # Redirect output to stderr. exec 1>&2 if [ "`git symbolic-ref HEAD | sed -e 's@^refs/heads/@@'`" = develop ] then echo "cannot commit on develop branch." exit 1 fi ``` などとするとできます. `git symbolic-ref HEAD` により `HEAD` が何であるか調べ, `develop` であれば `exit 1`で終了するという流れです. 参考ページにも詳しく書いてあるのですが, * `commit` の処理順序 2. `git commit` コマンドの実行 4. `pre-commit` フックの実行 6. デフォルトメッセージ生成 8. `prepare-commit-msg` フックの実行 10. コミットメッセージエディターが起動 12. `commit-msg` フックの実行 14. 実際にコミット生成 16. `post-commit` フックの実行 * `merge` の処理順序 2. `git merge` コマンドの実行 4. `prepare-commit-msg` フックの実行 6. 実際にマージの実行 8. `post-merge` フックの実行 となっています.そのため, `pre-commit` フックを使用すれば `git merge` はそのまま実行でき, `git commit` だけを実行禁止するか否かの判断ができます. ちなみに, `git commit --no-verify` でフックは回避できてしまうので注意してください. 参考: * Gitのフックの説明と挙動の検証 * Git hooks まとめ * Git-のカスタマイズ-Git-フック