[英]Get commit where merged branch forked from (with intermediate merge)
讓我們使用最新的git 2.16.2和tig 2.3.3。
cd /tmp && mkdir fit && cd fit
git init
touch m1 && git add m1 && git commit -m "master 1"
touch m2 && git add m2 && git commit -m "master 2"
git checkout -b develop
touch d1 && git add d1 && git commit -m "develop 1"
git checkout master
touch m3 && git add m3 && git commit -m "master 3"
git checkout develop
git merge master --no-edit
touch d2 && git add d2 && git commit -m "develop 2"
touch d3 && git add d3 && git commit -m "develop 3"
git checkout master
git merge develop --no-edit
touch m4 && git add m4 && git commit -m "master 4"
git reflog expire --expire=now --all && git gc --prune=now --aggressive
檢索develop
分支中的最后一個提交非常容易:
git --no-pager show -s --format=%B $(git rev-parse develop)
發展3
但是我無法在develop
分支中檢索到第一次提交 。 所以我找不到分支從哪里分支的提交。
git merge-base --fork-point develop
git rev-list develop..master
git rev-list develop master
git rev-list master develop
git rev-list ^develop master
結果沒有用。
我找到了一個問題的解決方案, 如何從合並分支分支的地方獲得提交
git oldest-ancestor master develop
git oldest-ancestor develop master
結果也沒有用。
但是, tig
和git log --graph
仍然能夠看到develop 1
是第一個提交的develop
分支,這個分支從分叉master 2
在提交master
。
是否可以使用當前的git控制台工具檢索master 2
?
git --no-pager show -s --format=%B $(git rev-parse develop)
更簡單:
git --no-pager show -s --format=%B develop
要么:
git --no-pager log --no-walk --format=%B develop
( show -s
和log --no-walk
幾乎是同一件事;這里的關鍵項是刪除不必要的git rev-parse
)。
但是我無法在
develop
分支中檢索到第一次提交
該分支中的第一個提交是master 1
或27ee6b8
中的27ee6b8
(哈希ID隨提交時間的不同而不同)。 這也是分支master
的第一次提交。
這里的問題是分支沒有“起點”。 從某種意義上說,分支是結構(即圖形片段),它是通過從終點開始然后再回到起點而到達的。 這意味着某些提交在許多分支上; 通常, 根提交是您在存儲庫中進行的第一次提交,位於每個分支上(盡管在具有多個根的存儲庫中,某些根可能不在某些分支上)。
通常,分支名稱 (有些例外)與該分支上的tip commit同義詞,這就是為什么您不需要顯式的git rev-parse
。 但是,分支名稱的主要特征是它會隨着時間的推移而移動 ,因此它總是命名分支的尖端提交。
另請參見“分支”到底是什么意思?
如果您希望標記某些特定的提交,以便以后記住它,通常的工具是Git標簽。 標簽非常類似於分支名稱,因為它標識一個特定的提交。 但是,與分支名稱不同,永遠不要移動標簽,並且Git不會自動移動標簽。
git reflog expire --expire=now --all
專門存在引用日志是為了能夠觀察引用的移動(隨時間變化)。 一個分支名狀的引用日志develop
保留,默認情況下為30天或90天,1散列ID的develop
用於識別。 通過使它們過期,您已經失去了回到過去並查看develop@1
, develop@2
等的功能。 如果保留了它們,則可以尋找現有的最古老的develop
。 那可能是它誕生的時候,您通常可以說:
05d0c47 master@{37}: clone: from ...
(表明此刻master
已出生)。
不幸的是,刷新日志確實會過期,因此這不是完全可靠的。 標簽是可靠的,但可能會令人討厭,因為git log
會用其標簽裝飾提交。 如果有尋找有趣的提交程序 ,你可以使用。 在這種情況下,有一個這樣的過程:您想要的合並曾經是或曾經是合並的提交。
要找到合並基礎,請找到合並本身,然后找到其父級:
m=11c63bc # this is the merge
p1=$(git rev-parse ${m}^1)
p2=$(git rev-parse ${m}^2)
現在$p1
和$p2
是此合並的兩個父級。 (一個合並可以有兩個以上的父級,但是大多數合並只有兩個。)最后兩個合並這兩個分支的共同點是兩個父級的合並基礎:
git merge-base --all $p1 $p2
由於只有一個合並基礎,因此只打印一個提交哈希。 如果有幾個,它將打印所有的,因為我們使用了--all
。 省略--all
,我們將(顯然)隨機地選擇一個(實際選擇的一個取決於用於查找合並基礎的算法)。
和以前一樣,不需要很多臨時變量,我們可以這樣做:
mbases=$(git merge-base --all ${m}^1 ${m}^2)
因為git merge-base
采用與git rev-parse
相同的commit-specifier語法: ^1
和^2
后綴在那里工作相同(並且實際上在大多數Git命令中工作)。
1到期時間是可配置的。 較短的時間(默認為30天)用於從引用的當前值無法訪問的哈希ID。 90天的默認較長時間是從引用的當前值可訪問的哈希ID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.