2017/11/26

Git の hook を使って merge line がある時には commit できないようにする

Git で merge した時に conflict すると
<<<<<<< HEAD
hoge
=======
fuga
>>>>>>> another-branch
view raw conflict.txt hosted with ❤ by GitHub
みたいな形で表示されます。これを解決して commit すれば問題解決。
しかし、複数部分が conflict していると、たまにこの線を commit することがあります。つらい。
それを阻止したいのですが、人の手でやることでは無いので自動化します。


man githooks

  • $ man git
    • とりあえず man を読む。
    • /hook とかすると githooks というものがあると。
  • $ man githooks
    • $GIT_DIR/hooks か core.hooksPath/* のファイルを読み込むと書いてあります。
    • hooksPath を設定してみます。~/.gitconfig あたりに
    • [core]
      hooksPath = ~/.config/git/hooks
      view raw .gitconfig hosted with ❤ by GitHub
    • を追記。
    • たぶん git confing --global とかでもできる。
    • 実際やることは ~/.gitconfig への書き込みだから同じなのだけれど。
    • これで全リポジトリに対する設定終わり。
  • ~/.config/git/hooks/pre-commit を書く
    • こんな感じかな。参考とか
    • #!/bin/sh
      FORBIDDEN='(<<<<<<<|=======|>>>>>>>)'
      GREP_COLOR='4;5;37;41'
      cd $PWD
      git diff --cached --name-only | xargs -L1 grep --color --with-filename -n -E $FORBIDDEN
      if [[ $? -eq 0 ]]; then
      echo "Merge lines was detected.\nPlease fix files, or run 'git commit --no-verify' to skip this check."
      exit 1
      fi
      view raw pre-commit hosted with ❤ by GitHub
    • これで commit 前に <<<<<< などの線があったら警告してくれます。
    • 実際は単なる shell script ですね。hook なので特定の action があった時に起動してれる感じ。
    • ちなみに git init したリポジトリの .git/hooks/* あたりを見ると sample があったりします。


動作サンプル

さて実際はどう動くかと言うと、こんな感じ。
$ git commit -m 'perfect merge'
e:1:<<<<<<< HEAD
e:3:=======
e:5:>>>>>>> o
Merge lines was detected.
Please fix files, or run 'git commit --no-verify' to skip this check.
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: hoge.txt
view raw result.txt hosted with ❤ by GitHub
commit したのに status が clean になってませんね。
これでミスって merge を解決し忘れたファイルを commit することも無いでしょう。めでたしめでたし。


おまけ

ソースにどうしても <<<<<< などの線を入れたい場合は
  • $ git commit --no-verify
とか使うと良いようです。
この hook を足す commit そのものが hook に引っかかったので使いました。


参考

0 件のコメント:

コメントを投稿