haya14busa

haya14busa’s memo

Git Mergetoolでvimdiffを便利に使う

Mergeしんどい

今までConflict起きたら直接コンフリクトしたファイルを編集して完全手動で直してたんですが、mergetoolの存在とかvimdiffとかで出来そうと思って調べました。

Gitの設定

git config –global merge.tool vimdiff
git config –global mergetool.prompt false
git config –global mergetool.keepBackup false

git config --global merge.conflictstyle diff3も紹介されていたけど共通祖先を表示する必要性を感じなかったので無視した。

promptをfalseにすることでmergetoolした時のpromptを省略して編集を始めるようにし、keepBackupをfalseにすることでmergetoolがデフォルトでは自動的に生成する*.origファイルを生成しないように出来る。

Vimの設定

“ Mapping for vimdiff
” for git mergetool
if &diff
  map <Leader>1 :diffget LOCAL<CR>
  map <Leader>2 :diffget BASE<CR>
  map <Leader>3 :diffget REMOTE<CR>
  map <Leader>u :<C-u>diffupdate<CR>
  map u u:<C-u>diffupdate<CR>
endif

左から1,2,3って覚え方でよさそう。Local,Base,Remoteの頭文字とかでもKeymapに余裕があるならよさそう。

一度diffgetしたあとUndoするとdiffがうまく効かないのでuにdiffupdateを噛ませてる

]c,[cで次/前のConflict箇所にジャンプするので気に入らなければお好みでキーマップ書くとよさげかも。

終了時には:wqa or :qaあたりを使うのでこれもキーマップしたほうがストレス減るかも知れない。

vimdiff or vimdiff2 or vimdiff3?

$ git config –global mergetool.gvimdiff3.cmd ‘gvim -f -d -c “wincmd J” “$MERGED” “$LOCAL” “$BASE” “$REMOTE”’
$ git config –global mergetool.vimdiff3.cmd ‘vim -f -d -c “wincmd J” “$MERGED” “$LOCAL” “$BASE” “$REMOTE”’

toofishes.net - Three-way merging for git using vim

git config --global merge.tool [toolname]で設定

最初はvimdiff3の記事を見つけてやってみたんだけど、共通祖先がない場合にBASEがないだけでなく、diffの挙動がちょっとおかしい。
おそらく存在しないBASEと比較してしまうのでファイル全体がdiff1つ分の対象となってしまっている。

git/mergetools/vimdiff at master · git/git

そこで調べてみるとそもそもデフォルトで提供されているvimdiffが3-way mergingに対応してるっぽい。どっかのタイミングで受け入れられたのかな?

そちらを試してみると、共通祖先(BASE)がある場合は3-way(3-column and MERGE)になって、共通祖先がない場合は2-way view(3-column LOCAL, MERGED, REMOTE)として正しく表示される。

場合によってUIが変わってしまうのは良くないとはいえ、正しくdiffれることが優先なのでvimdiffを標準で使うことにした。

$ git config --global merge.tool vimdiff

MERGED、つまりコンフリクトを解消する実際に扱ってるファイル(バッファ)を2-wayの時でも下の段に持って行きたい場合は<C-w>Jで出来る。(自動化するためにラッパー書きました↓)

vimdiff2は強制的に2-wayにするっぽいのでとりあえず却下。

vimdiffのwrapper書こう

vimdiffのUIが3column(中心がMerged)だったり、3column(LOCAL, BASE, REMOTE) + Marged でBaseの有無で変わってしまうのはどうかと思うので対応したかった。

haya14busa/git-mergetool-vimdiff-wrapper

シェルスクリプトよくわかんなくてつらい。 引数で渡されたBASEをtest -sで調べて条件分岐させてます。

必ず実際に作業するMERGEDペインが一番下に来るのでよさげ

git-merge-sandbox

haya14busa/git-merge-sandbox

調べている間にeiel/git-merge-sandboxを見つけて便利だった(& 若干の不満があった)ので自分でも作ってみた。

wrapperの(完全手動)テストもこれを使った

変更点

  1. Merge後にコミットしてしまっても動く
  2. BASE(共通祖先のファイル?)の有無でdiffの種類が2つに分かれている

Git tag

ちょうどgitのtagを使えてないなーと思っていたのでtagを使う練習にもなってよかった。

$ git tag -a [tagname] -m'Comment' (checusum)
$ git push origin –tags

Link

Comments