git 1.9/2.0 Q1 2014 以降では、Aristotle Pagaltzisの回答で説明されているように、書き換えられた上流ブランチにリベースする前に、以前のブランチの起点をマークする必要はありません。コミット 07d406bとコミット d96855f
を
参照してください。
topic
で作成されたブランチで作業した後git checkout -b topic origin/master
、リモート トラッキング ブランチの履歴origin/master
が巻き戻されて再構築された可能性があり、次のような履歴になります。
o---B1
/
---o---o---B2--o---o---o---B (origin/master)
\
B3
\
Derived (topic)
以前origin/master
は commits を指していましたが、B3
現在は を指しており、あなたのブランチは が だったときにその上で開始されました。B2
B1
B
topic
origin/master
B3
このモードでは、 の reflog をorigin/master
フォークB3
ポイントとして使用してtopic
、更新された の上に をリベースできるようにorigin/master
します。
$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic
そのため、git merge-base
コマンドには新しいオプションがあります。
--fork-point::
ブランチ (または につながる履歴<commit>
) が別のブランチ (または任意の参照) から分岐したポイントを見つけます<ref>
。
これは、2 つのコミットの共通の祖先を探すだけでなく、 の reflog も考慮して、以前のブランチの化身からフォークされ<ref>
た履歴があるかどうかを確認し<commit>
<ref>
ます。
" git pull --rebase
" コマンドは、base
" " ベース" が " "ブランチは巻き戻され、再構築されました。
たとえば、履歴が次のようになっているとします。
base
" " ブランチの現在の先端は にありますB
が、以前のフェッチでは、その先端
が現在のコミットに到達する前に、そして次にB3
あったことが観察されました。B2
B1
B3
最新の「ベース」の上にリベースされているブランチは commitに基づいています。
現在のヒント " " の祖先であるコミットが見つかるまで、" " の出力 (つまり、、、、)をB3
調べgit rev-list --reflog base
てB
見つけようとします。B1
B2
B3
Derived (topic)
内部的には、get_merge_bases_many()
これを一度に計算できます。" " の過去のすべてのヒントをマージすることによって生じる架空のマージ コミットとの
間のマージ ベースが必要です。
そのようなコミットが存在する場合、" " の reflog エントリの 1 つと完全に一致する単一の結果が得られるはずです。Derived
base (origin/master)
base
Git 2.1 (2014 年第 3 四半期) は、この機能をより堅牢にする機能を追加します。John Keepingによるcommit 1e0dacdを参照してください ( )johnkeeping
次のトポロジがあるシナリオを正しく処理します。
C --- D --- E <- dev
/
B <- master@{1}
/
o --- B' --- C* --- D* <- master
どこ:
B'
の修正バージョンでありB
、パッチと同一ではありませんB
。
C*
およびはそれぞれ およびとD*
パッチが同一であり、間違った順序で適用するとテキストが競合します。C
D
E
にテキスト的に依存しD
ます。
の正しい結果git rebase master dev
は、 が とのB
分岐点として識別されるため、、、は に対してリプレイする必要があるコミットです。ただし、 andはand and and soとパッチが同一であるため、削除できるため、最終結果は次のようになります。dev
master
C
D
E
master
C
D
C*
D*
o --- B' --- C* --- D* --- E <- dev
分岐点が識別されない場合、B
を含むブランチを選択B'
すると競合が発生し、パッチと同一のコミットが正しく識別されない場合、(または同等の)C
を含むブランチを選択すると競合が発生します。D
D*
" " の " --fork-point
" モードはgit rebase
、2.20 時代にコマンドを C で書き直すと後退しましたが、Git 2.27 (Q2 2020) で修正されました。
Junio C Hamano ( )によるコミット f08132f (2019 年 12 月 9 日)を参照してください。( 2020 年 3 月 27 日、コミット fb4175bでJunio C Hamanoによってマージされました)gitster
gitster
rebase
:--fork-point
回帰修正
署名者: Alex Torok
[jc: 修正を改良し、Alex のテストを使用]
署名者: Junio C Hamano gitster@pobox.com
" " は、短い refname を処理し、基になる関数を呼び出す前に完全な refname に dwim する方法を知っているgit rebase --fork-point master
" " を内部的に呼び出していたため、問題なく動作していました。git merge-base --fork-point
get_fork_point()
これは、コマンドが C で書き直された後は当てはまりません。これは、直接行われた内部呼び出しがget_fork_point()
短い参照を dwim しないためです。
「git merge-base」で使用されている「refname引数を完全なrefnameにdwimする」ロジックを基になるget_fork_point()
関数に移動して、「git rebase」の実装で関数の他の呼び出し元が同じように動作するように修正しますこの回帰。
Git 2.31 (2021 年第 1 四半期) では、" git rebase --[no-]fork-point
" ( man ) " に構成変数が追加rebase.forkPoint
されたため、ユーザーはデフォルト以外の設定を指定し続ける必要がなくなりました。
commit 2803d80 (2021 年 2 月 23 日) by Alex Henrie ( alexhenrie
)を参照してください。
( 2021 年 2 月 25 日、コミット 682bbadでJunio C Hamanoによってマージされました)gitster
rebase
: の構成オプションを追加します--no-fork-point
署名者: Alex Henrie
一部のユーザー (私自身を含む) は、コミットをサイレントにドロップできるため、デフォルトでこの機能をオフにすることを好みます。
git config
manページに含まれるようになりました:
rebase.forkPoint
false に設定--no-fork-point
すると、デフォルトでオプションが設定されます。