セットアップと設定
プロジェクトの取得と作成
基本的なスナップショット
ブランチとマージ
プロジェクトの共有と更新
検査と比較
パッチ
デバッグ
メール
外部システム
サーバー管理
- 2.43.1 → 2.47.0 変更なし
-
2.43.0
11/20/23
- 2.39.1 → 2.42.3 変更なし
-
2.39.0
12/12/22
- 2.24.1 → 2.38.5 変更なし
-
2.24.0
11/04/19
- 2.23.1 → 2.23.4 変更なし
-
2.23.0
08/16/19
- 2.19.3 → 2.22.5 変更なし
-
2.19.2
11/21/18
- 2.16.6 → 2.19.1 変更なし
-
2.15.4
12/06/19
- 2.11.4 → 2.14.6 変更なし
-
2.10.5
09/22/17
- 2.1.4 → 2.9.5 変更なし
-
2.0.5
12/17/14
概要
git merge-base [-a | --all] <commit> <commit>… git merge-base [-a | --all] --octopus <commit>… git merge-base --is-ancestor <commit> <commit> git merge-base --independent <commit>… git merge-base --fork-point <ref> [<commit>]
説明
git merge-base は、3方マージで使用される2つのコミット間の最良の共通祖先(複数可)を見つけます。 ある共通祖先は、後者が前者の祖先である場合、別の共通祖先よりも「優れています」。 より良い共通祖先を持たない共通祖先は、最良の共通祖先、つまりマージベースです。 コミットのペアには、複数のマージベースが存在する可能性があることに注意してください。
動作モード
最も一般的な特殊なケースでは、コマンドラインに2つのコミットのみを指定すると、指定された2つのコミット間のマージベースが計算されます。
より一般的には、マージベースを計算する2つのコミットのうち、1つはコマンドラインの最初のコミット引数で指定されます。 もう一方のコミットは、コマンドラインの残りのすべてのコミットをマージした(仮想的な可能性のある)コミットです。
その結果、2つ以上のコミットが指定されている場合、マージベースは必ずしも各コミット引数に含まれているわけではありません。これは、--merge-base
オプションを付けて使用した場合のgit-show-branch[1]とは異なります。
- --octopus
-
n方マージの準備として、提供されたすべてのコミットの最良の共通祖先を計算します。これは、git show-branch --merge-baseの動作を模倣しています。
- --independent
-
マージベースを出力する代わりに、同じ祖先を持つ提供されたコミットの最小限のサブセットを出力します。つまり、指定されたコミットの中で、他のコミットから到達できないものをリストします。これは、git show-branch --independentの動作を模倣しています。
- --is-ancestor
-
最初の<commit>が2番目の<commit>の祖先であるかどうかを確認し、真の場合はステータス0で終了し、偽の場合はステータス1で終了します。エラーは、1ではないゼロ以外のステータスで示されます。
- --fork-point
-
ブランチ(または<commit>につながる履歴)が別のブランチ(または参照)<ref>から分岐した点を検出します。これは、2つのコミットの共通祖先を探すだけでなく、<ref>のreflogも考慮して、<commit>につながる履歴がブランチ<ref>の以前のバージョンから分岐したかどうかを確認します(このモードの詳細については後述)。
詳細
2つのコミットAとBが与えられると、git merge-base A B
は、親の関係を通してAとBの両方から到達可能なコミットを出力します。
例えば、次のトポロジーの場合
o---o---o---B / ---o---1---o---o---o---A
AとBのマージベースは1です。
3つのコミットA、B、Cが与えられると、git merge-base A B C
は、BとCのマージである仮想的なコミットMとAのマージベースを計算します。 例えば、次のトポロジーの場合
o---o---o---o---C / / o---o---o---B / / ---2---1---o---o---o---A
git merge-base A B C
の結果は1です。これは、BとCの間のマージコミットMを持つ同等のトポロジーが
o---o---o---o---o / \ / o---o---o---o---M / / ---2---1---o---o---o---A
であり、git merge-base A M
の結果が1であるためです。コミット2もAとMの共通祖先ですが、2は1の祖先であるため、1はより良い共通祖先です。したがって、2はマージベースではありません。
git merge-base --octopus A B C
の結果は2です。なぜなら、2がすべてのコミットの最良の共通祖先だからです。
履歴にクロスオーバーマージが含まれている場合、2つのコミットに対して複数の最良の共通祖先が存在する可能性があります。 例えば、次のトポロジーの場合
---1---o---A \ / X / \ ---2---o---o---B
1と2の両方がAとBのマージベースです。どちらが良いわけでもありません(どちらも最良のマージベースです)。--all
オプションが指定されていない場合、どちらの最良のものが出力されるかは指定されていません。
2つのコミットAとBの間の「高速転送」をチェックするための一般的なイディオムは(少なくとも以前は)、AとBの間のマージベースを計算し、それがAと同じであるかどうかを確認することでした。その場合、AはBの祖先です。このイディオムは、古いスクリプトで頻繁に使用されているのがわかります。
A=$(git rev-parse --verify A) if test "$A" = "$(git merge-base A B)" then ... A is an ancestor of B ... fi
最新のGitでは、より直接的な方法で表現できます。
if git merge-base --is-ancestor A B then ... A is an ancestor of B ... fi
代わりに。
フォークポイントモードに関する説明
git switch -c topic origin/master
で作成されたtopic
ブランチで作業した後、リモート追跡ブランチorigin/master
の履歴が巻き戻されて再構築された可能性があり、次の形状の履歴になります。
o---B2 / ---o---o---B1--o---o---o---B (origin/master) \ B0 \ D0---D1---D (topic)
ここで、origin/master
は以前はコミットB0、B1、B2を指していましたが、現在はBを指しており、origin/master
がB0にあったときにその上にtopic
ブランチが開始され、その上にD0、D1、Dの3つのコミットが作成されました。今、更新されたorigin/masterの上にtopicで行った作業をrebaseしたいとします。
このような場合、git merge-base origin/master topic
は、上の図でB0の親を返しますが、B0^..Dは、Bの上に再生したいコミットの範囲ではありません(作成しなかったB0を含みます。これは、先方がB0からB1に先端を移動したときに破棄したコミットです)。
git merge-base --fork-point origin/master topic
はこのような場合に役立つように設計されています。Bだけでなく、B0、B1、B2(つまり、リポジトリのreflogが認識するリモート追跡ブランチの古い先端)も考慮して、topicブランチが作成されたコミットを特定し、B0を見つけます。これにより、先方が後で破棄したコミットを除いて、topic上のコミットのみを再生できます。
したがって
$ fork_point=$(git merge-base --fork-point origin/master topic)
はB0を見つけ、
$ git rebase --onto origin/master $fork_point topic
はD0、D1、DをBの上に再生して、次の形状の新しい履歴を作成します。
o---B2 / ---o---o---B1--o---o---o---B (origin/master) \ \ B0 D0'--D1'--D' (topic - updated) \ D0---D1---D (topic - old)
注意点として、リポジトリの古いreflogエントリはgit gc
によって期限切れになる可能性があります。B0がリモート追跡ブランチorigin/master
のreflogに表示されなくなった場合、--fork-point
モードは明らかにそれを検出できず、失敗し、ランダムで役に立たない結果(--fork-point
オプションなしの同じコマンドが返すB0の親など)を与えることを回避します。
また、--fork-point
モードを使用するリモート追跡ブランチは、topicがその先端から分岐したものでなければなりません。先端よりも古いコミットから分岐した場合、このモードは分岐点を検出しません(上記のサンプル履歴でB0が存在せず、origin/masterがB1で始まり、B2、次にBに移動し、origin/masterがB1であったときにorigin/master^でtopicを分岐したと想像してください。履歴の形状は上記と同じで、B0はありません。git merge-base origin/master topic
が正しく検出するB1の親ですが、--fork-point
モードは検出しません。なぜなら、それはorigin/masterの先端にあったコミットではないからです)。
GIT
git[1]スイートの一部