マージの取り消しとマージのリセット
私の推測では、あなたは実際には Already-up-to-date
.
問題は、git revertがマージを元に戻さず、マージによってもたらされた変更のみを元に戻すことです。マージ コミットを作成すると、これら 2 つのブランチのコミット履歴が結合されます。
マージ
develop
|
A---B---C
\ \
E---F---M
|
newfeature
上記の場合、develop
は にマージされnewfeature
、M
コミットが作成されます。実行git log newfeature
すると、両方のブランチからのすべてのコミットが表示されますが、ブランチの観点からは、newfeature
これらの変更はすべてM
コミットによって実行されました。
元に戻す
このgit revert
コマンドはコミットを削除するのではなく、コミットに含まれていた変更を元に戻す新しいコミットを作成します。たとえば、この差分を含むコミットがあった場合...
-This is the old sentence.
+This is the new sentence.
次に、これを元に戻しました。revert コマンドは、反対の diff を実行したばかりの新しいコミットを作成し、単に符号を反転します。
-This is the new sentence.
+This is the old sentence.
これは、他の開発者が既に持っているコミットによって引き起こされたダメージを元に戻すのに非常に役立ちます。歴史を変えるのではなく、歴史を前進させます。
マージを元に戻す
ただし、非早送りマージのコンテキストでは、望ましくない効果が生じる可能性があります。
develop
|
A---B---C
\ \
E---F---M---W
|
newfeature
git log newfeature
W が復帰コミットであると仮定すると、実行中に開発ブランチからのすべてのコミットが引き続き含まれることがわかります。その結果、develop
ブランチから欠落しているものは何も表示されないため、からの追加のマージは機能しません。
元に戻す代わりにgit resetを使用します。
将来、git reset --hard <ref>
(<ref>
はマージのコミット ハッシュ) を使用して、そのマージが他の開発者と共有されていない場合にマージを元に戻すことを検討する必要があるかもしれません。上記の例では、 merge commit を作成した後M
にコマンドgit reset --hard F
を実行すると、次のようになります。
develop
|
A---B---C
\ \
E---F---M
|
newfeature
おわかりのように、このテクニックは一部の人々が考える傾向があるようにコミットを消去するものではなく、選択したコミットにブランチを戻すだけです。実行すると、 git log newfeature
commit F
、E
、およびのみが取得されますA
。これでマージは実際にブランチの履歴から削除されたので、後で再マージを試みてdevelop
も問題は発生しません。
この方法には複雑さが伴います。履歴を変更していることに注意してください。したがってnewfeature
、マージ後にブランチがリモート ブランチにプッシュされた場合M
、git は単に時代遅れであると判断し、実行する必要があることを通知しますgit pull
。そのリモートブランチで作業しているだけなら、お気軽にforce-push
- git push -f <remote> <branch>
. これは、リセットと同じ効果がありますが、リモート ブランチに影響します。
このブランチが複数の開発者によって使用されており、その開発者が既にそこからプルしている場合、これは悪い考えです。git revert
実際の履歴を変更せずに変更を元に戻すため、これが便利な理由です。
履歴でリセットを使用することは、実際には共有されていないコミットのオプションのみです。
解決策 - 復帰を元に戻す。
マージ コミットが既に共有されている場合、最善の方法はおそらくgit revert
そのマージで使用することです。ただし、前に述べたように、ブランチを単純にマージして戻し、そのブランチからのすべての変更が再表示されることを期待することはできません。答えは、revert コミットを元に戻すことです。
develop
でのマージを尊重した後、ブランチでいくつかの作業を行ったとしましょうnewfeature
。あなたの履歴は次のようになります。
develop
|
A---B---C---D
\ \
E---F---M---W
|
newfeature
今マージdevelop
した場合、ブランチの履歴の一部ではない唯一のコミットであるため、newfeature
取得するだけです。また、そのコミットを元に戻す必要があります。D
newfeature
W
git revert W
git merge develop
develop
|
A---B---C-----------D
\ \ \
E---F---M---W---M---G
|
newfeature
これにより、元のマージ コミットによって行われたすべての変更が復元されます。実際にはC
およびによって行われましたが、B
元に戻されました。新しいマージ コミットを介してW
取り込まれます。最近の変更を にマージする前に元に戻すことをお勧めします。この順序で競合が発生する可能性が低くなります。D
G
develop
TL;DR
元に戻すと、「元に戻すコミット」が作成されます。復帰を元に戻す場合は、最初に復帰したときに作成された復帰コミットに対して revert コマンドを実行する必要があります。見つけるのは簡単なはずです.gitは元に戻すと自動コメントする傾向があるため、「元に戻す」という単語で始まります。
git revert <commit>