38

私はもともと 'newfeature' ブランチで働いていましたが、ライブ ブランチのバグを緊急に修正するように呼ばれました。「generalmaintenance」と呼ばれるブランチを作成し、仕事をしてから、開発に切り替えてマージしました。「newfeature」ブランチに戻り、以前にマージした変更をマージしたいと思います。

「newfeature」に切り替えて「develop」でマージすると、3 つのファイルで競合が発生しました。

競合を解決するのに苦労し、最終的に Aptana Studio 3 (私の IDE) の「チーム」メニューにある「元に戻す」コマンドを使用することにしました。私はこれがマージの前に私をロールバックすることを期待していました。

とにかく、もう一度「開発」にマージすると、Already-up-to-dateと表示されますが、2 つのブランチ間でファイルを比較すると、それらは非常に異なっており、もう一方のブランチに追加した変更はマージされていません。

2 つのブランチをマージするにはどうすればよいですか?

4

3 に答える 3

71

マージの取り消しとマージのリセット

私の推測では、あなたは実際に Already-up-to-date.

問題は、git revertがマージを元に戻さず、マージによってもたらされた変更のみを元に戻すことです。マージ コミットを作成すると、これら 2 つのブランチのコミット履歴が結合されます。

マージ

     develop
        |
A---B---C
 \       \
  E---F---M
          |
      newfeature

上記の場合、developは にマージされnewfeatureMコミットが作成されます。実行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 newfeatureW が復帰コミットであると仮定すると、実行中に開発ブランチからのすべてのコミットが引き続き含まれることがわかります。その結果、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 newfeaturecommit FE、およびのみが取得されます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取得するだけです。また、そのコミットを元に戻す必要があります。DnewfeatureWgit revert Wgit merge develop

                 develop
                    |
A---B---C-----------D
 \       \           \
  E---F---M---W---M---G
                      |
                 newfeature

これにより、元のマージ コミットによって行われたすべての変更が復元されます。実際にはCおよびによって行われましたが、B元に戻されました。新しいマージ コミットを介してW取り込まれます。最近の変更を にマージする前に元に戻すことをお勧めします。この順序で競合が発生する可能性が低くなります。DGdevelop

TL;DR

元に戻すと、「元に戻すコミット」が作成されます。復帰を元に戻す場合は、最初に復帰したときに作成された復帰コミットに対して revert コマンドを実行する必要があります。見つけるのは簡単なはずです.gitは元に戻すと自動コメントする傾向があるため、「元に戻す」という単語で始まります。

git revert <commit>

于 2013-04-01T04:33:04.843 に答える