Git:2つのブランチの最新の共通祖先を見つけます


844

2つのGitブランチの最新の共通の祖先を見つける方法は?


3
最新の定義:実際の時間、コミット数、その他の指標?
Ciro Santilli冠状病毒审查六四事件法轮功

2
関連(十字形マージ):stackoverflow.com/questions/26370185/...は
jub0bs

1
@CiroSantilli新疆改造中心996ICU六四事件それはどの指標でも同じですよね?
YakovL

@YakovL私は、分岐のため、およびコミットオブジェクトに任意のコミット日付を設定できるため、そうは思わない。その日付自体は、おそらく望んでいるものではない。
Ciro Santilli冠状病毒审查六四事件法轮功

1
@CiroSantilli新疆改造中心996ICU六四事件ツリーの最後の一般的なコミットの前に、より古いタイムスタンプを持つコミットがある場合にのみ、違いがあるように思えます。ささいな例を提供できますか?
YakovL

回答:


1019

あなたが探していgit merge-baseます。使用法:

$ git merge-base branch2 branch3
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

85
これは最も最近の共通の祖先を見つけることに注意してください...質問者が望んでいるものだと私は信じているので、+ 1。ちょうどそれを注意して、ケースには誰もが検索しようとここに来て最も古い:も参照、これのために- (私が行ったように)共通の祖先をstackoverflow.com/questions/1527234/...
lindes

16
@funroll:またはその省略形:git log master...HEAD
CBベイリー

17
@lindes最も古い共通の祖先は最初のコミットではないでしょうか?
–ThorbjørnRavn Andersen 2015

8
@ThorbjørnRavnAndersen、はい、そうだと思います...説明が難しいのは、gitが有向非巡回グラフを使用しているにもかかわらず、技術的にはツリーではないとしばしば考えられているためです。私の言い回しでより注意を払うために、「分岐」の最初のインスタンスの親を分岐させたい場合について話していました...それらは複数のポイントを再マージおよび再分割する場合があるため、これはこれらの "最も古い"ですが、本当に最も古い祖先ではありません。これは、(最初​​は)常に最初のコミットです。
lindes 2015

5
この質問は厳密には2つのブランチの共通の祖先を見つけることに関するものですが、3つ以上のブランチの共通の祖先を希望する場合--octopusは、正しい結果を得るためにフラグを渡す必要があることに注意してください。明白だが間違っているgit merge-base branch1 branch2 branch3とコミットが得られますが、ドキュメントの「ディスカッション」セクションで説明されているように、3つのブランチすべての共通の祖先であるとは限りません
Mark Amery

46

git diff master...feature

現在の(おそらくマルチコミット)機能ブランチのすべての新しいコミットを表示します。

man git-diff 以下の文書:

git diff A...B

と同じです:

git diff $(git merge-base A B) B

しかし、...入力して覚える方が簡単です。

Daveが述べたように、の特殊なケースはHEAD省略できます。そう:

git diff master...HEAD

と同じです:

git diff master...

現在のブランチがの場合、これで十分ですfeature

最後に、順序が重要であることを忘れないでください!実行git diff feature...masterすると、オンでmasterはない変更が表示されfeatureます。

私はもっ​​と多くのgitコマンドがその構文をサポートすることを望みますが、それらはサポートしないと思います。そして、いくつかは異なるセマンティクスを持っています...Gitコミット範囲のダブルドット「..」とトリプルドット「...」の違いは何ですか?


8
またはgit diff master...、diffの特殊なケースHEAD
Dave

「...」は私にとってpowershellでは機能しませんでした、面白いことにgitコンソールで機能しましたが、おそらくリポジトリが完全ではなかったため、git diff $(git merge-base AB)Bが実行しました。私はこれがブランチをマージするかもしれないと少し懐疑的でした:)
Moiz Ahmed

1
ワオ。かなり素晴らしい。必要なブランチがまだチェックアウトされていないためにローカルリポジトリに存在しない場合は、単純に行うことができますgit diff origin/branchname...
Mark Ch

25

以前の回答で述べたように、git merge-base動作します:

$ git merge-base myfeature develop
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

myfeature現在のブランチである場合は、よくあることですが、次のように使用できます--fork-point

$ git merge-base --fork-point develop
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

この引数は、十分に新しいバージョンのgitでのみ機能します。残念ながら、それが常に機能するとは限らず、その理由は明らかではありません。この回答の終わりに記載されている制限を参照してください。


完全なコミット情報については、以下を検討してください。

$ git log -1 $(git merge-base --fork-point develop) 

持っていgit version 2.14.1.windows.1ます。現在のブランチから分岐したことわかっgit merge-base --fork-point branch2いるブランチ(独自のコミットを使用)で実行しても、結果は得られませんが、フォークポイントは正しく表示されます。何が問題でしょうか?git merge-base branch1 branch2
ADTC、2017年

@ADTCチェックアウトbranch2してから実行しgit merge-base --fork-point branch1ます。
Acumenus 2017年

@ADTC gitkなどのグラフィカルなコミットビューアを使用して、ツリーの外観を確認します。多分あなたはあなたの答えを得るでしょう。
Acumenus 2017年

グラフィカルに表示すると、ツリーについて奇妙なことは何もありません。パスをたどって、の結果に一致する共通の祖先を見つけることができますgit merge-base branch1 branch2。しかし、奇妙なことに、それ--fork-pointはどちらの方法も与えません。意図したとおりに機能することを確認しましたか?
ADTC、2017年

1
@ADTCと同じです。コマンド「git log -1 $(git merge-base --fork-point anotherBranch)」は、gitバージョン2.16.2.windows.1を使用した結果を表示しません。
マジンジャー

10

ではgitk、あなたグラフィカルに二つの枝を表示することができます。

gitk branch1 branch2

そして、2つのブランチの履歴から共通の祖先を見つけるのは簡単です。


6
すべてのケースですべてが視覚的に実行できるわけではありません。プログラムで自動化する必要がある理由はいくつかあります。
ADTC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.