メモの日々


2017年01月10日(火) [長年日記]

[dev][howto] Gitでブランチのマージを取り消してやり直す

Gitでブランチのマージを取り消し、ブランチを修正して再度マージする方法をメモ。マージ元のブランチをbranch1、マージ先のブランチをmasterとする。

マージの取り消し

[master] ---o---o---M---x
	           /
[branch1]  ---A---B

Mでbranch1をmasterへマージしたけどこれを取り消したい。このときはgit revertを使うのが簡単そう。

% git checkout master
% git revert -m 1 M

これで

[master] ---o---o---M---x---W
	           /
[branch1]  ---A---B

という状態になって、masterにMで入った変更は元に戻る。マージコミットに対するgit revertには-mオプションが必要なのが面倒。-m 1がデフォルトではいかんのか。

ブランチをもう一度マージする

上の後でbranch1に修正を加えて再びmasterへマージするにはどうするか。

[master] ---o---o---M---x---W---x---?
	           /               /
[branch1]  ---A---B-----------C---D

普通にマージしてしまうとAとBの変更がmasterにマージされない。

Undoing MergesにあるようにmasterブランチにWを取り消すコミットをした後でbranch1をmasterへマージすればいいみたいだけれど、マージの直前にmasterを更新するというのは危ういと感じる。マージし忘れる可能性があるから。

git revertのマニュアルからリンクされているrevert-a-faulty-merge.txtを読めば理解が進むと思われるが長いので読んでいない。

にあるようにWをbranch1に取り込んだ後でbranch1上でWを取り消すというのはいいように思ったのだけれど、試してみるとこうしてもAとBの変更はmasterに反映されなかった。なんでや。

なので、「ブランチをもう一度マージする」いい方法はわからない。

新しいブランチでやり直す

仕方ないので、マージのやり直しは次のように新しいbranch2を作って行えばいいと思う。

[master] ---o---o---M---x---W
	           /         \
[branch1]  ---A---B           \
                               \
[branch2]                       R

branch2ではRでWを取り消す。こうすればAとBが復活する。

% git checkout master
% git branch -b branch2
% git revert W

そのあとでCとDの変更をしてNでマージする。

[master] ---o---o---M---x---W---x-----------N
	           /         \             /
[branch1]  ---A---B           \           /
                               \         /
[branch2]                       R---C---D
(CとDのコミットをした後)
% git checkout master
% git merge branch2