簡體   English   中英

Git:簽出到標簽后2次提交

[英]Git: checkout to 2 commit after a tag

知道以下方案: 在此處輸入圖片說明

黃線是Master分支。 紅線是Develop分支。

我在標簽6.2.1的Master上。 我需要自動獲取以藍色圈出的提交的sha1,簽出到此sha1,然后從此sha1創建我的分支。 該提交不是開發的最后一個提交。

可能要做的事情包括:

  • 得到標簽6.2.1的sha1: git log --oneline | head -1 | cut -d ' ' -f1 git log --oneline | head -1 | cut -d ' ' -f1
  • 獲取標簽6.2.1的父級:稱為提交'P'
  • 得到下面的“ P”提交,稱為提交“ C1”,應該在開發中
  • 在開發中也獲得了以下名為“ C2”的“ C1”提交。

目前,我必須手動執行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尖端 ,它是合並提交。 它有兩個父母: DG 當我們檢查提交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提供兩點信息:

  1. 請以v2.1結尾
  2. 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 *之后執行“三步”提交,則可以為CG 使用git rev-list tag..branch將打印所有的AH (以某種順序)。 添加--first-parent將切斷G C這兩個中只有一個可以成為H第一父級-並且如果要查看兩者,則不能使用--first-parent 添加--ancestry-path將使git rev-list忽略DEF ; 其余的仍然會以某種順序出現。 添加--topo-order可以確保B排在倒數第二位,而A在最后(請記住,Git在向后工作), CG按任何順序排列,而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標志在這里,因為它從不可逆的列表開始計數並停止,並且我們不知道將有多少個提交,我們想要從下至上的第二個提交,但實際上是第二個。

打開git bash,轉到所選目錄,然后運行以下命令。 獲取SHA1運行命令

git log branchname --oneline

提交消息旁邊將有sha1

在此處輸入圖片說明

git branch branchname <sha1-of-commit>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM