web-dev-qa-db-ja.com

あるコミットが別のコミットの祖先であるかどうか(またはその逆)を確認するにはどうすればよいですか?

Gitはスナップショットの [〜#〜] dag [〜#〜] であり、グラフ上の各ノードはコミットを表します。各コミットは「n」個の親コミットを持つことができます。

2つのコミットがある場合、DAGでこれら2つのコミットの「順序」を識別する単一の簡潔な方法はありますか。 git rev-listが最も有望なようですが、適切な呪文を見つけることができません。

理想的には、私は次のようなものを持っているでしょう

$ git related hash1 hash2
hash1 is ancestor of hash2

OR

hash2 is ancestor of hash1

OR

hash1 unrelated to hash2

OR

hash1 is equal to hash2
62
Chris Cleeland

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

これに対する答えを見つける方法は複数あります。最も簡単なのは使用することです

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

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

--is-ancestor

最初の<commit>が2番目の<commit>の祖先であるかどうかを確認し、trueの場合はステータス0で終了し、そうでない場合はステータス1で終了します。エラーは、1以外のゼロ以外のステータスによって通知されます。

その他のオプション

三重ドット...表記のgitログ

もう1つのオプションは、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)を含むブランチのみをリストします。

65
user456814

次のシェルスクリプトは、トリックを行う可能性があります。

if git rev-list $SHA1 | grep -q $SHA2 ; then echo "$SHA2 is ancestor of $SHA1"
Elif git rev-list $SHA2 | grep -q $SHA1 ; then echo "$SHA1 is ancestor of $SHA2"
else echo "$SHA1 unrelated to $SHA2" ; fi

または、それをgitエイリアスにきれいにまとめます:

git config --global alias.related '!function git_related() { if git rev-list $1 | grep -q $2 ; then echo "$2 is ancestor of $1" ; Elif git rev-list $2 | grep -q $1 ; then echo "$1 is ancestor of $2" ; else echo "$1 unrelated to $2" ; fi } ; git_related $1 $2'
9
helmbert
if   (( $(git rev-list $1..$2|wc -l) == 0 )); then echo "$2 is ancestor of $1"
Elif (( $(git rev-list $2..$1|wc -l) == 0 )); then echo "$1 is ancestor of $2"
else echo "$1 and $2 are unrelated"
fi
2
michas
git log  --oneline -1  OLD_SHA..NEW_SHA

これによりログが提供される場合、OLD_SHAはNEW_SHAの親です。

1
jin

@helmbertの優れたgit relatedエイリアス、これはブランチID(またはHEADなど))を引数として受け入れるだけでなく、IDをコミットするバージョンです。

git config --global alias.related '!function git_related() { commit1=`git log -n 1 --format="%h" $1` ; commit2=`git log -n 1 --format="%h" $2` ; if git rev-list $commit1 | grep -q $commit2 ; then echo "$2 is ancestor of $1" ; Elif git rev-list $commit2 | grep -q $commit1 ; then echo "$1 is ancestor of $2" ; else echo "$1 unrelated to $2" ; fi } ; git_related $1 $2'
0
Peter Reay