リポジトリにブランチ master と A があり、この 2 つの間で多くのマージ アクティビティが行われています。ブランチ A が master に基づいて作成されたときのコミットをリポジトリ内で見つけるにはどうすればよいでしょうか?
私のリポジトリは基本的に次のようになります:
-- X -- A -- B -- C -- D -- F (master)
\ / \ /
\ / \ /
G -- H -- I -- J (branch A)
リビジョン A を探していますが、見つかりませんgit merge-base (--all)
。
ベストアンサー1
私も同じことを探していたのですが、この質問を見つけました。質問していただきありがとうございます。
しかし、ここで見た回答は、あなたが求めていた(または私が探していた)回答とはまったくG
異なるものであるように思われます。コミットではなくコミットが示されているようですA
。
そこで、テストできるように次のツリー (文字は時系列順に割り当て) を作成しました。
A - B - D - F - G <- "master" branch (at G)
\ \ /
C - E --' <- "topic" branch (still at E)
これはあなたのものとは少し違って見えます。なぜなら、私が(あなたのグラフではなくこのグラフを参照して)Bを取得し、A(およびDやE)を取得しなかったことを確認したかったからです。SHAプレフィックスとコミットメッセージに添付されている文字は次のとおりです(私のリポジトリは以下からクローンできます)。ここ(もし誰かにとって興味深いなら):
G: a9546a2 merge from topic back to master
F: e7c863d commit on master after master was merged to topic
E: 648ca35 merging master onto topic
D: 37ad159 post-branch commit on master
C: 132ee2a first commit on topic branch
B: 6aafd7f second commit on master before branching
A: 4112403 initial commit on master
目標は、 B を見つけることです。少しいじってみて、私が見つけた 3 つの方法は次のとおりです。
1. gitk を使って視覚的に:
視覚的には次のようなツリーが表示されます (マスターから見た場合)。
またはここ(トピックから見ると):
B
どちらの場合も、グラフ内のコミットを選択しました。それをクリックすると、グラフのすぐ下のテキスト入力フィールドに完全な SHA が表示されます。
2. ターミナルから視覚的に:
git log --graph --oneline --all
(編集/補足: 追加すると、--decorate
ブランチ名やタグなどの表示が追加されるので、興味深いこともあります。以下の出力ではその使用が反映されないため、上記のコマンドラインには追加しません。)
これは次のことを示しています( と仮定git config --global color.ui auto
)。
または、直接テキストで言うと:
* a9546a2 トピックからマスターにマージ |\ | * 648ca35 マスターをトピックにマージ中 | |\ | * | 132ee2a トピックブランチの最初のコミット * | | マスターがトピックにマージされた後にマスターにe7c863dコミット | |/ |/| * | 37ad159 マスターでのブランチ後のコミット |/ * 6aafd7f ブランチ前のマスターでの 2 番目のコミット * 4112403 マスターへの最初のコミット
B
どちらの場合でも、6aafd7f コミットは、私のグラフでもあなたのグラフでも、最小共通点として見られますA
。
3. シェルマジックの場合:
質問では、上記のようなものが欲しかったのか、それとも 1 つのリビジョンだけを取得して他には何もしない単一のコマンドが欲しかったのかを指定していません。では、後者の場合は次のとおりです。
diff -u <(git rev-list --first-parent topic) \
<(git rev-list --first-parent master) | \
sed -ne 's/^ //p' | head -1
6aafd7ff98017c816033df18395c5c1e7829960d
これを~/.gitconfigに次のように記述することもできます(注意:末尾のダッシュは重要です。ブライアンこの点に注意を喚起してくれたことに感謝します。
[alias]
oldest-ancestor = !zsh -c 'diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne \"s/^ //p\" | head -1' -
これは、次の(引用符で囲んだ複雑な)コマンドラインで実行できます。
git config --global alias.oldest-ancestor '!zsh -c '\''diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne "s/^ //p" | head -1'\'' -'
注:zsh
とすることも簡単にできますbash
が、動作sh
しません。この<()
構文は標準の には存在しませんsh
。(このページの別の回答へのコメントでこのことを教えてくれた @conny に改めて感謝します!)
注: 上記の代替バージョン:
感謝リオリのために指摘上記は、同一のブランチを比較するときに失敗する可能性があるので、sed 形式をミックスから削除し、これを「より安全」にする (つまり、マスターとマスターを比較する場合でも結果 (つまり、最新のコミット) を返す) 代替の diff 形式を考え出しました。
.git-config 行として:
[alias]
oldest-ancestor = !zsh -c 'diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | head -1' -
シェルから:
git config --global alias.oldest-ancestor '!zsh -c '\''diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | head -1'\'' -'
したがって、私のテスト ツリー (しばらくの間利用できませんでしたが、現在は復活しています) では、マスターとトピックの両方で機能するようになりました (それぞれコミット G と B になります)。liori さん、代替形式を提供してくれてありがとうございました。
それで、私 [と liori] が思いついたのがこれです。私の場合はうまく機能しているようです。また、便利なエイリアスがいくつか追加されます。
git config --global alias.branchdiff '!sh -c "git diff `git oldest-ancestor`.."'
git config --global alias.branchlog '!sh -c "git log `git oldest-ancestor`.."'
ハッピーギット!