コンフリクト解消中のGitブランチを、作業途中でプッシュしたい


「upstreamのmasterブランチをマージしようとしたら大量のコンフリクトが発生した」こと、ありませんか?

私はよくあります

「せっせっとコンフリクトを解消してるけど、そろそろ時間切れ。このブランチ、いったんプッシュしたいなぁ」ということ、ありませんか?

私はよくあります

ですが、未処理のコンフリクトを残したままコミットしようとしても、

$ git commit
error: 'commit' is not possible because you have unmerged files.
hint: Fix them up in the work tree,
hint: and then use 'git add/rm <file>' as
hint: appropriate to mark resolution and make a commit,
hint: or use 'git commit -a'.
fatal: Exiting because of an unresolved conflict.

(意訳:コンフリクトの解決終わってないからコミットなんてできません~)

とGitに怒られてしまうわけです。そこをなんとか……ということで、とりあえず作業状態を一時保存(コミット)してプッシュしておいて、あとからなんとかする方法を模索してみます。

ツッコミ大歓迎です

一時保存の方法

コンフリクト解消作業中に以下のコマンドを実行すれば、「とりあえず作業状態を一時保存(マージコミット)してプッシュ」できます。

$ git add .
$ git commit
$ git push <リモート名> <マージ作業中のブランチ名>

一時保存した内容を別端末にプルしたら、コンフリクト解消作業を再開しましょう。

  1. コンフリクト未解消ファイルの状態に応じて、下記の手順でコンフリクト状態を復元する
  2. 復元されたファイルを使って、コンフリクトを解消する
  3. コンフリクトが解消できたら、git add <fileapth> ; git commit --amend で、該当ファイルをマージコミットに追加する

コンフリクト解消前のファイルを一時保存した場合

まずはコンフリクトを一切解消していない状態のファイルから。このコマンドを実行すると、一度コミットしたファイルを、マージ直後のコンフリクト解消前状態に戻せます。

$ git checkout --conflict=merge <filepath>

Gitもこのファイルを「コンフリクト未解消」とみなしてくれますので、マージツールなどとの連携もいつもどおり可能です。

コンフリクト解消中のファイルを一時保存した場合

上のコマンドだけだと「マージ直後のコンフリクト解消前」の状態に戻ってしまうので、「コンフリクトを途中まで解消した一時保存の状態」はなくなってしまいます。それはつらい……ということで、git showコマンドの出番です。

$ git checkout --conflict=merge <filepath>
$ git show HEAD:<filepath> > <filepath>

こうすれば、一時保存状態を再現しつつ、Gitがこのファイルを「コンフリクト未解消」とみなしてくれるようになります。

注意

  1. マージ作業用のブランチを前もって作成しておく
  2. あとでgit push -fしても問題ないリモートを使う

ようにしましょう。一時保存なコミットをmasterブランチに直接追加するのはのは避けるべきですし、「git push -fだめ、絶対っ!」というルールがあるリポジトリ(リモート)もたくさんあるからです。