LoginSignup
25
12

More than 1 year has passed since last update.

Git hooks pre-commitを使って意図しない変更のpushを防ぐ

Posted at

はじめに

突然ですが、こんな経験ありませんか?

:confounded:< featureブランチにpushしたつもりがdevelopにpushしてしまった!
:confounded:< pushしてからデバッグコードの消し忘れに気づいた!

どちらかを経験したことがある方は多いのではないでしょうか?(恥ずかしい話ですが私もあります...)
pushする前だったらローカルでcommitの取り消しができますが、
一度pushしてしまうとその差分は履歴として残るし、それを消すにしても消した履歴も残ってしまいますよね。
できることならpushする前に気づいてそっと修正したい...!
ということで、
今回は「git commit した時にスクリプトを実行することで意図しない変更がpushされないようにする」をやっていきます。

やり方

やりたいことは「git commit した時に任意のスクリプトを実行する」ことなので、
今回はGit フックpre-commitを使っていきます。
似たようなことができる機能でGitHub Actionsがありますが、トリガーにcommitがないので今回はpre-commitを使っていきます。
pre-commitとは、以下Git フックより

pre-commit フックは、コミットメッセージが入力される前に実行されます。 これは、いまからコミットされるスナップショットを検査したり、何かし忘れた事がないか確認したり、テストが実行できるか確認したり、何かしらコードを検査する目的で使用されます。 このフックがゼロでない値を返すと、コミットが中断されます。

つまり、コミット前に任意のスクリプトを実行し、そのスクリプトが0を返すとコミットがそのままされ、ゼロ以外を返すとコミットが中断されます。
今回はこれを利用します。

実装

まずはスクリプトを用意します。下記の通りにコマンドを実行してください。

$ mkdir tmp
$ cd tmp
$ git init

適当なディレクトリを作成し、そこで$ git initを実行しました。これで.gitという隠しディレクトリができているはずです。
続いて下記コマンドを実行します。

$ cd .git
$ cd hooks
$ ls
applypatch-msg.sample       pre-applypatch.sample       pre-rebase.sample
commit-msg.sample           pre-commit.sample           pre-receive.sample
fsmonitor-watchman.sample   pre-merge-commit.sample     prepare-commit-msg.sample
post-update.sample          pre-push.sample             update.sample

隠しディレクトリ内のhooksディレクトリに移動します。そこの中身をみてみるといろいろなサンプルスクリプトがあることがわかります。
これらは末尾の.sampleを消去すればそのまま動きます。
今回はここに自作のスクリプトを追加します。

$ vi pre-commit

上記コマンドでpre-commitというファイルを作成してください。(拡張子はなくて大丈夫です)
作成したファイルに下記を追記してください。

BRANCH_NAME=`git symbolic-ref HEAD | sed -e 's:^refs/heads/::'`
if test $BRANCH_NAME = master -o $BRANCH_NAME = develop; then
    echo "${BRANCH_NAME} への直コミットは禁止されています。"
    exit 1
fi

files=`git status|grep -e "modified" -e "new file"|sed "s/new file:\(.*\)/\1/g"|sed "s/modified:\(.*\)/\1/g"|cut -f 2`

for file in $files
do
   result=`less $file | grep -e "console.log"`;

   if [ -n "$result" ]; then
       echo "${file} にデバッグ文が入っています。";
       exit 1
    fi
done

次に、作成したファイルに対して実行権限を与えてあげます。

$ chmod +x pre-commit

pre-commitが動作しているか確認します。
ここでは例としてconsole.log('hoge');と記載されたreadme.mdというファイルを用意します。

$ git checkout master
$ git add readme.md
$ git commit -m 'test commit'
master への直コミットは禁止されています。

$ git checkout feature
$ git commit -m 'test commit'
readme.md にデバッグ文が入っています。

いずれの場合もコミットできていないはずです、
featureブランチにてconsole.log('hoge'); を削除すると正しくコミットできるはずです。

参考

25
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
12