web-dev-qa-db-ja.com

git rebaseを使用すると、同じ競合が再び表示されるのはなぜですか?

SOでgit mergeとgit rebaseに関連する質問を読みましたが、内部で何が起こっているのかまだ完全には理解できません。

分岐状況は次のとおりです。

MASTER------------------------
        \        \
         \        \----Feature B---
          \                        \
           \-----Feature A----------\---Feature A+B

異なる時点でmasterから派生する2つの機能ブランチがあります。2つのブランチを結合したいと考えています。 first rebase then merge練習しますが、機能Aを機能Bにリベースすると、競合が発生します。両方の機能(およびマスター)が同じ領域で変更されているため、これは予想されています。しかし、奇妙なことは、git rebase --continue。これは私たちを夢中にさせるので、リベースを中止し、git merge。競合は実際に簡単に解決できることがわかりました。

私の質問は2つあります。

  1. git rebase私たちの状況に適していますか?または、リベースは、わずかな(1または2)変更をプルするのに適していますか?
  2. 同じ紛争を何度も繰り返し発生させるフードの下で何が起こっていますか?私の理解では、rebaseは1つずつ競合を解決しますが、どのコミットを何と比較するのですか?

SOに関連する投稿:

35
NeoWang

Rebaseはあなたの状況に適していますか?

Feature AおよびFeature Bsharedブランチであるという事実に基づいて、私は言うno

リベースはブランチをマージする方法で、マージコミットを持たずに(つまり、2つ以上の親を持つコミット)を線形履歴として表示します。local branchesのマージに最適です。これは、ローカルリポジトリにのみ存在し、他の人に公開されていないブランチです。どうして?少なくとも2つの理由のため:

  1. リベースにより、コミットID(つまり、メタデータのSHA-1ハッシュ)が変更されます。これは、リベースされたコミットをshared branchにプッシュすると、完全にnew commitsとして表示されることを意味しますたとえ同じ変更がまだ含まれている場合でも、ローカルリポジトリでそれらを取得する人。現在、誰かがその間に古いコミットの上に新しいコミットを追加した場合、彼らはそれらを移動する必要があります。これにより、不必要な混乱が生じます。

  2. パブリックブランチをマージするとき、多くの場合、wantでそれらをmerge commitsにして、コミット方法を追跡できるようにします。ブランチ間を移動しました。その情報はリベースすると失われます。

フードの下で何が起こっているのですか?

ただの定期的なマージ。違いは、git rebase一度に1つのコミットをマージすることです共通の親から開始する前のコミットの上に。 git mergeは、2つのコミットとその変更セット全体を1つの操作としてマージするため、競合を1回解決するだけで済みます。

更新:繰り返し発生する競合の解決

@Jubobsがコメントで指摘したように、Gitには、複数回発生する競合を解決するための自動化されたソリューションがあります: git rerere 、または "記録された解像度を再利用」。

マージの競合が発生するたびに、構成ファイル(rerere.enabled true)でrerereを有効にすると、Gitは競合するファイルの状態を記録しますbeforeおよびafterをマージします。次回、同じ競合が発生します–マージの両側でexact same linesを含む競合– Gitは以前に記録した同じ解像度を自動的に適用します。また、マージ出力でそれについて通知します。

CONFLICT(コンテンツ): 'somefile'の競合のマージ
以前の解像度を使用して「somefile」を解決しました。

ここで、 詳細git rerereを使用して競合を処理する方法を見つけることができます。

46