[英]Git: checkout to 2 commit after a tag
黃線是Master分支。 紅線是Develop分支。
我在標簽6.2.1的Master上。 我需要自動獲取以藍色圈出的提交的sha1,簽出到此sha1,然后從此sha1創建我的分支。 該提交不是開發的最后一個提交。
可能要做的事情包括:
git log --oneline | head -1 | cut -d ' ' -f1
git log --oneline | head -1 | cut -d ' ' -f1
目前,我必須手動執行Gitlab,在簽出之前獲取相關的sha1,然后創建我的分支。
有辦法,但是有潛在的問題。
標簽名稱標識提交。
更確切地說,像v2.1
這樣的標記名稱是完全限定的引用名稱refs/tags/v2.1
的簡短版本,任何Git引用都標識一些Git對象。 所有分支名稱(例如master
,是refs/heads/master
縮寫)都被約束為僅標識提交對象。 標記名稱通常標識提交對象(Git將此稱為輕量級標記)或帶注釋的標記對象,然后繼續標識提交。 在這兩種情況下, 特殊的gitrevisions語法 name ^{commit}
指特定的提交(如果您需要的話)(通常不需要)— Git指出,例如git checkout
需要一個提交並自動添加^{commit}
)。
問題是,您不希望標記標識的提交。 您想要附近的提交。 您說過“兩次提交之后 ”,這是一個問題:沒有另一次提交之后的提交。 在其他提交之前只有提交。
如果在提交之前有提交,怎么可能在提交之后沒有提交呢? 例如,讓我們連續寫下四個提交:
A <- B <- C <- D
在Git中,提交D
存儲其父提交(即提交C
的ID。 因此,給定D
,很容易退回到C
同樣, C
存儲B
的ID, B
存儲A
的ID。 (如果A
是有史以來的第一個提交,則沒有父提交:您不能后退,而A
是根提交 。根提交是沒有父提交的。)
這里的問題是,就此而言,在提交之前或之后可能有多個提交。 不僅僅是上述內容,請考慮以下圖形片段:
A--B--C--D---H <-- master
\ /
E--F--G <-- feature
提交H
是分支master
的尖端 ,它是合並提交。 它有兩個父母: D
和G
當我們檢查提交H
我們看到這樣的東西(具有不同的數字):
$ git show master
commit 3e5c63943d35be1804d302c0393affc4916c3dc3
Merge: c13c783 20690b2
這意味着它有兩個父母, c13c783...
和20690b2...
哪一個是提交前提交H
?
因此,對此異議的答案是,在提交之前沒有提交,在另一個提交之前可能有很多 (通常是1,有時是2,稀有,但有時是零,或三或更多)提交。 同樣, 在另一個提交之后可能沒有任何提交,或者有兩個或多個提交。
要查找的commit()你想 ,你需要更多的信息。
通常,向后移動很容易。 提交的第一個 (通常是唯一的 )父級通常是有趣的一個,因為是該提交被添加到該分支之前在該分支上的提交。 也就是說,盡管提交H
具有D
和 G
作為父母,但如果master
過去一直指向D
並現在指向H
,則它是我們想要的H
的第一個父母。
Gitrevisions具有用於跟隨初生父母的快速簡便的語法:您只需添加波浪號~
字符和后退多少初生父母的計數即可。 所以要從v2.1
退后兩步,只跟隨第一個父母,只需編寫v2.1~2
:
git checkout -b newbranch v2.1~2
到此為止。
前進比較困難。 Git僅存儲向后鏈接,因此您需要做的是提供以后提交的名稱或身份,Git可以從中向后工作以達到您的已知(帶標簽)提交。 例如,如果我們有一個指向提交C
的標簽,並且想向前移動兩個步驟(到D
然后到H
),我們將為Git提供兩點信息:
v2.1
結尾 master
開始 並枚舉這兩點之間的所有提交,然后選擇比v2.1
的最后一步“更容易master
”的前兩個步驟。 假設此時, master
上有更多提交,因此圖形如下所示:
tag:v2.1
|
v
A--B--C--D---H--I <-- master
\ /
E--F--G <-- feature
為了以這種方式找到H
,我們使用git rev-list
和更多的gitrevisions語法 。 (現在,很明顯, 學習gitrevisions語法對於使用Git至關重要 。)
git rev-list v2.1..master
這里的兩點語法表示“ 不包括v2.1
本身”,因此這將列出從master提交到v2.1
之后的提交的提交:
0fbc341... # id of I
a9315c3... # id of H
9911231... # id of D
我們獲取這些ID的最后兩個,丟棄這些ID的最后一個 ,得到a9315c3
,它是H
的ID。
如果圖形看起來更像這樣呢?
tag:v2.1
|
v
A--B--C--D---------H--I <-- master
\ /
E--F--G <-- feature
前面我們注意到,使用~
表示法使用第一個父代。 我們可以在這里使用git rev-list --first-parent v2.1..master
做到這git rev-list --first-parent v2.1..master
。 這將使Git無法上市GFE
,這將確保我們找到H
而不是E
最好在rev-list命令中添加--topo-order
,因為否則這些提交將按commit-date順序列出,並且日期/時間是否曾經被弄錯了,在存儲庫中,提交可能以錯誤的順序列出。
還有--ancestry-path
選項,該選項在某些情況下很有用(可能不適用於您自己的情況):它確保git rev-list
僅列出..
操作左側后代的提交..
。 您可以在--first-parent
地方使用它,例如:
...--o--*--A--B--C
\ \ \
D--E--F--G--H <-- branch
如果我們希望在標記的commit *
之后執行“三步”提交,則可以為C
或G
使用git rev-list tag..branch
將打印所有的A
到H
(以某種順序)。 添加--first-parent
將切斷G
或 C
這兩個中只有一個可以成為H
的第一父級-並且如果要查看兩者,則不能使用--first-parent
。 添加--ancestry-path
將使git rev-list
忽略DEF
; 其余的仍然會以某種順序出現。 添加--topo-order
可以確保B
排在倒數第二位,而A
在最后(請記住,Git在向后工作), C
和G
按任何順序排列,而H
位於第一。
這不是一個完整的解決方案,但是如果您有一個這樣的分支並合並圖,則沒有完整的解決方案。
無論如何,選擇這些選項的一些子集。 如果您知道您的圖是第一父級的,那么,例如:
git rev-list --topo-order --first-parent tag .. branchname | tail -2 | head -1
將為您提供所需的哈希值。
(對於另一個微妙的技巧,請添加--reverse
以反轉git rev-list
的打印輸出順序,然后使用sed -n -e 2p
打印第二行。但是請注意,您不能使用git rev-list
的-n
標志在這里,因為它從不可逆的列表開始計數並停止,並且我們不知道將有多少個提交,我們想要從下至上的第二個提交,但實際上是第二個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.