TL;DR コンフリクトを解決した後は git reset
まずはstash
git stash
でローカルの変更内容を退避。もしくは
git stash push -m "message"
で説明を付けて退避する。
-p
オプションを使うとgit add -p
のように好きな部分を選んで退避できる。
ワーキングツリーのstashされた部分は最後のコミット直後の状態に戻るのでここで好きな作業などをする。
例えば別のコミットをしてそこから更に変更を加えたりなど。
退避した変更を戻して適用するには
git stash pop
直近のstashエントリーを適用して無事終わったら削除
もしくは
git stash apply
直近のstashエントリーを適用
git stash drop
直近のstashエントリーを削除
コンフリクトが発生しなかったらめでたしめでたし。
もし未コミットな変更があると以下のように言われてしまうのでその変更をコミットしたりこれもまたstash pushする(popするときはstashの名前を指定する必要が出てくるけど)などして対処する。もし未コミットな変更もpopするときに混ぜたいなら全部git add
だけしてgit stash pop --index
すると良い。
error: Your local changes to the following files would be overwritten by merge:
*
Please commit your changes or stash them before you merge.
Aborting
コンフリクト発生
もしコンフリクトが発生したら以下のように表示される。
CONFLICT (content): Merge conflict in *
コンフリクトしたファイル内容は以下のようになっているので<<<
や>>>
などで検索し手動でマージして解決する。>>>や<<<<や===などの行は削除する。手動ではなくstashの内容を全採用したいならgit checkout --theirs
などの方法もある。
...
<<<<<<< Updated upstream
適用先の内容
=======
退避した内容
>>>>>>> Stashed changes
...
そしてこの時点でコンフリクトが発生しなかった他のファイルはステージング(git addした状態)されている。またコンフリクトを解決したファイルもgitの内部状態ではコンフリクトしたままなのでgit reset
して一括でunstageしてやる。これでgit内部のコンフリクト状態も解決するし、git diff
ですべての変更点が表示されるようになる。
git reset
ではなくコンフリクトしていたファイルをgit add
してもgit内部のコンフリクト状態が解消されるのですぐにコミットするつもりならgit add
でも良い。
その他
git stash list
stashエントリー一覧
git stash show -p stash@{1}
一つ前のエントリの内容を表示
git stash list --pretty=oneline
各stashのハッシュ値を表示
stashで退避した後に過去のコミットへ戻って作業するときはgit checkout ハッシュ
で戻れます。
作業が終わった後に最新のコミットへ帰って来るときはgit checkout master
などブランチ名で戻るようにしましょう。ハッシュ名などで戻るとdetached HEADの状態(匿名のブランチを作った状態)が継続したままなので新たなコミットを行うとツリーが分岐してしまいます。
戻ったときにgit branch
で* (HEAD detached at ハッシュ)
となったらdetached HEADの状態です。またgit log
でも確認できます。(HEAD, master)となっていたらdetached HEADの状態になっています。(HEAD -> master)となっていればOKです。
https://stackoverflow.com/questions/7751555/how-to-resolve-git-stash-conflict-without-commit
https://git-scm.com/docs/git-stash