1. ホーム
  2. git

あるコミットが別のコミットの祖先であるかどうか(あるいはその逆かどうか)を見分けるにはどうしたらよいですか?

2023-11-26 05:47:33

質問

Git は DAG であり、グラフ上の各ノードがコミットを表します。各コミットは「n」個の親コミットを持つことができます。

任意の 2 つのコミットがある場合、DAG 内のこれら 2 つの "order"を識別するための単一の簡潔な方法はありますか。 git rev-list が最も有望であると思われますが、正しい呪文を見つけることができないようです。

理想を言えば、次のようなものです。

$ git related hash1 hash2
hash1 is ancestor of hash2

または

hash2 is ancestor of hash1

または

hash1 unrelated to hash2

または

hash1 is equal to hash2

どのように解決するのですか?

使用方法 git merge-base --is-ancestor <commit1> <commit2>

これに対する答えを見つける方法は1つだけではありません。最もシンプルなのは

git merge-base --is-ancestor <possible-ancestor-commit> <commit>

のドキュメントから git merge-base :

--is-ancestor

最初の <commit> の祖先であるかどうかを調べます。 <commit> であり、真の場合はステータス 0 で、真の場合はステータス 1 で終了する。エラーは1でない0でないステータスで通知されます。

その他のオプション

トリプルドット付きの git ログ ... という表記があります。

もう一つの選択肢は git log で、トリプルドット記法を使用する ... で、子コミットの集合和から集合和を引いたものを出力するように Git に指示します。基本的に、これはコミットの集合が互いにどのように分岐したかを示すものです。

$ git log --oneline --graph --left-right \
--first-parent --decorate <commit1>...<commit2>

上記のコマンドは、以下の場所から到達可能なコミットを表示します。 commit1 または commit2 というように、セット操作の観点から、C1 UNION C2 - C1 INTERSECTION C2というように、両方ではありません。

どちらのコミットも他方の親でない場合は、両方の子コミットが表示されますが、一方が他方の祖先である場合は、祖先が子孫のパスに含まれているため、子孫コミットの出力だけが表示され、出力から除外されます。

についてもっと読むことができます。 git log とトリプルドット記法については、以下の資料を参照してください。

  1. git-log(1) .
  2. gitrevisions(1): 範囲の指定 .
  3. リビジョン選択 .

git branch --contains オプション

git-rev-list(1) は、この答えに使えそうな気がします。もうひとつの方法は、テストしたいコミットに一時的なブランチラベルをつけるだけで、そのコミットに対して --contains オプションで git branch :

git branch --contains <commit-to-test>

出力されるのは、コミットツリーのどこかにそのコミットを含むすべてのブランチです。そのため、他のコミットで一時ブランチを使用することで、テストしているコミットが先祖に当たるかどうかを確認することができます。

ドキュメントより。

--contains [<commit>]

指定したコミットを含むブランチのみをリストアップします(指定しない場合はHEAD)。