TL;DR (2018 年 5 月追加)
Git では内部の仕組みがすぐにわかるようになっているため、基本的に全体が少し混乱しています。
ここで関係するケースは、実行時に発生することに注意してください。
git checkout somebranch; git rebase origin/their-branch
または類似。マージの競合を強制的に解決するために、リベースが一時的に停止しました。その後、競合を解決してgit add実行することになっていますgit rebase --continue。(何らかのマージ ツールをgit mergetoolや洗練された GUI インターフェースと共に使用する場合、そのインターフェースは別の方法でこれの一部またはすべてを実行する場合がありますが、その下ではgit add、解決されたファイルを ing して実行していgit rebase --continueます。)
最初に、HEADコミットは彼らのブランチであるため、git checkout --oursorを使用するとgit checkout --theirs、彼らの最後のコミットを--ours意味し、あなたがリベースする最初のコミットを意味します。これは通常の日常的な Git の混乱であり ( 「git における "ours" と "theirs" の正確な意味は何ですか? を参照)、元の質問につながったものではありません。origin/their-branch--theirs
ただし、後で、HEADコミットは実際には一種の混合物です。これは、いくつかのコミットを最新の commit の上にコピーした結果です。部分的に構築された新しい一連のコミットと、独自の元のコミットとの間で競合が発生しています。この競合の原因は、通常、「彼ら」が行ったものです (途中で変更されたものorigin/their-branch)。この競合を解決する必要があります。そうすると、後のコミットでまったく同じ競合が再発することがあります。
繰り返しますが、HEADorlocalまたは--oursはrebase が変更とその変更を組み合わせて構築したコミットであり、もう 1 つのコミット ( remoteor>>>>>>>または--theirs) は、rebase がコピーしようとしている独自のコミットHEADです。
より長いです
マージ (内部で繰り返される「マージ」の特殊なケースであるリベースを含む) には、2 つの「ヘッド」(2 つの特定のブランチ チップ) が関係します。your-branchこれらを呼び出しましょうorigin/their-branch:
G - H -------- <-- HEAD=your-branch
/ \
... - E - F M <-- desired merge commit [requires manual merge]
\ /
I - J - K - L <-- origin/their-branch
この点は、一般的に (そして当然のことながら) 混乱を招きますが、このようにラベル付けすると十分に明確になります。
さらに悪いことに、git は--oursと--theirsを使用して、マージ中に 2 つのヘッド コミットを参照します。「ours」は、実行Hしたときのコミット (commit )git mergeであり、「theirs」は、まあ、彼らの (commit L) です。しかし、リベースを実行しているときは、2 つのヘッドが逆になるため、"ours" はリベース先のヘッド (つまり、更新されたコード) であり、"theirs" は現在リベースしているコミットです。つまり、独自のコードです。
これは、rebase が実際に一連のチェリー ピック操作を使用するためです。ほとんど同じ画像から始めます。
G - H <-- HEAD=your-branch
/
... - E - F
\
I - J - K - L <-- origin/their-branch
ここで git がしなければならないことは、commitとの効果をコピーすることです。しかし、それを行うには、git は最初に内部的にコミットするように切り替える必要があります(「切り離された HEAD」モードを使用):GHgit cherry-pickGHL
G - H <-- your-branch
/
... - E - F
\
I - J - K - L <-- HEAD, origin/their-branch
Fこれで、コミットのツリーを比較しG(変更内容を確認するため)、Fvsを比較しL(作業の一部が既に にあるかどうかを確認するためL)、まだ変更されていない変更を取得しLて追加することで、リベース操作を開始できます。これは、内部的には「マージ」操作です。
G - H <-- your-branch
/
... - E - F G' <-- HEAD
\ /
I - J - K - L <-- origin/their-branch
マージがうまくいかない場合は、HEADまだ commit のままですL(commitG'がまだ存在しないため)。したがって、はい、HEAD開発部門の責任者です。少なくとも、現在はそうです。
ただし、のコピーがG存在すると、 にHEAD移動し、git は からの変更を同じ方法でG'コピーしようとします( diff vs 、次に diff vs 、結果をマージします)。HGHFG'
G - H <-- your-branch
/
... - E - F G' - H' <-- HEAD
\ /
I - J - K - L <-- origin/their-branch
繰り返しますが、マージが失敗して助けが必要な場合は、 as がまだ存在しない代わりに を指すことにHEADなります。G'H'H'
マージがすべて成功し、コミットG'しH' て存在するようになると、git はyour-branchcommit からラベルを削除し、代わりHに commit を指すようにします。H'
G - H
/
... - E - F G' - H' <-- HEAD=your-branch
\ /
I - J - K - L <-- origin/their-branch
あなたは今リベースされ、HEAD再びあなたが期待するものです. ただし、リベース中HEADは、ブランチ チップ ( commit L) か、ブランチ チップを越えてコピーおよび追加された新しいコミットの 1 つです。and--oursは、コミットがコピー元 (またはそれ以上)であることLを意味します。--theirsGH
(これは基本的に、git が行うことの生のメカニズムを公開する gitであり、git ではかなり頻繁に発生します。)