我有以下分支:
xxx@box:~/src$ git branch
jira_6500
* main
xxx@box:~/src$ git rev-parse main
bfd271932228f8ce33b68b82ffee5ee3b2386a17
xxx@box:~/src$ git rev-parse jira_6500
bfd271932228f8ce33b68b82ffee5ee3b2386a17
xxx@box:~/src$
我嘗試從標簽創建一個新分支v2.6.0-rc3,如下所示:
xxx@box:~/src$ git rev-parse v2.6.0-rc3
ff8db8992102ca7ce76f55169d06173c888c9447
xxx@box:~/src$ git checkout -b test001 v2.6.0-rc3
Switched to a new branch 'test001'
xxx@box:~/src$ git branch
jira_6500
main
* test001
然后我檢查新分支的 rev 哈希。我希望和標簽一樣v2.6.0-rc3。但事實并非如此。它與jira_6500分支相同。
xxx@box:~/src$ git rev-parse test001
bfd271932228f8ce33b68b82ffee5ee3b2386a17
我做了與下面的執行緒相同的事情。我記得我以前這樣做過。
rev 哈希值怎么會出錯?
如何從標簽創建新分支?
uj5u.com熱心網友回復:
你的分支創建的作業,你會希望它的方式。您所看到的原因與 Git 標簽的內部結構有關,這有點奇怪。
Git 在其小小的 gitty 心臟中,都是關于commits 的,這些commits由哈希 ID 編號,通常以十六進制表示:bfd271932228f8ce33b68b82ffee5ee3b2386a17例如。
為了使提交作業,Git 需要另外兩個內部支持物件,Git 將它們稱為tree和blob。這些也有哈希 ID。您通常不會看到這些哈希 ID:它們不會“泄露”太多。(不過,Blob 哈希 ID 確實顯示index:在git diff輸出的行中,如果您查找它們,您可以找到樹哈希:這些都不是隱藏的。它們只是不像提交哈希 ID 那樣全部出現在您的面前。 )
標簽,在 Git 中,標記一個提交——但你在這里有一個選擇:一個輕量級標簽直接保存一個提交哈希 ID,所以如果你有 commit bfd27...,你可以創建一個輕量級標簽來存盤該哈希 ID。不過,如果您想存盤更多資訊,Git 有一個支持物件,稱為標記物件或帶注釋的標記物件。我們讓 Git 創建這些物件之一,存盤額外的資料——例如 PGP 簽名或其他什么——并且該物件獲得自己唯一的哈希 ID,例如ff8db8992102ca7ce76f55169d06173c888c9447.
該標簽物件本身存盤,與注釋資料一起,所述提交散列ID, bfd271932228f8ce33b68b82ffee5ee3b2386a17。由于這些哈希 ID 各自唯一標識對應的物件,因此 Git 可以通過讀取標記物件并找到存盤的提交哈希 ID ,使用標記IDff8db...來查找提交物件。(這是不可能的:bfd27...在我們創建任何指向它的標簽之前,提交是一成不變的,因此我們以后不能將這些標簽 ID添加到提交中。所以,像往常一樣使用 Git,我們必須向后作業,從較新的物件到較舊的物件。)
使用git rev-parse v2.6.0-rc3,您可以獲得帶注釋的標簽物件的哈希 ID。從這里 Git 可以找到提交。標簽名稱可以直接指向一個提交——同樣,這使它成為一個輕量級標簽——或者指向一個標簽物件,使標簽名稱成為一個帶注釋的標簽。Git 可以通過任何一種方式找到提交。
與標簽名稱不同,分支名稱受到限制:它們可能僅包含某些(現有)提交的哈希 ID 。所以當創建一個新的分支名稱時,如果你給 Git 一個帶注釋的標簽物件的哈希 ID,或者一個決議為帶注釋的標簽物件的名稱,Git 會繼續跟隨帶注釋的標簽物件到它的目標,這需要是一個犯罪。1
所以這正是你在這里看到的。創建分支名稱跟隨標記到標記提交。其他分支名稱也指向同一個提交——這很好也很正常。當您使用git checkout或“打開”這些分支名稱之一git switch并進行新提交時,Git 將照常進行新提交,并且作為 的最后一步git commit,將新提交的哈希 ID 寫入當前分支名稱,導致分支前進。
使用git checkout v2.6.0-rc3或簽出標簽git switch --detach v2.6.0-rc3將使 Git 進入分離的 HEAD模式,其中HEAD包含提交的原始哈希 ID。在這種情況下,進行新提交會將新提交的哈希 ID 直接存盤在特殊名稱中HEAD,而不是任何分支名稱中。這意味著重新附加(使用分支名稱而不是提交哈希 IDHEAD覆寫HEAD存盤槽)會“丟失”新提交,這就是您通常不會在 detached-HEAD 模式下執行新作業的原因。2
這里還有最后一件事要提,那就是git rev-parse有一堆句法技巧來處理這個問題。它們都包含在gitrevisions 檔案中,但在此處快速概述相關內容很有用:
git rev-parse v2.6.0-rc3只為您提供v2.6.0-rc3決議為的任何 ID :在這種情況下,refs/tags/v2.6.0-rc3決議為帶注釋的標簽。git rev-parse v2.6.0-rc3^{commit}找到與:關聯的提交,v2.6.0-rc3也就是說,如果這是一個標簽,它會剝離標簽并要求結果是一個提交。git rev-parse v2.6.0-rc3^{tree}找到與關聯的樹v2.6.0-rc3:也就是說,如果這是一個標簽,它會剝掉標簽;如果這是一次提交,它會查找存盤在該提交中的頂級樹;它要求最終結果是樹的哈希 ID。git rev-parse v2.6.0-rc3^{}找到與 關聯的散列 IDv2.6.0-rc3,如果是標簽,則剝離標簽(然后成功停止并生成散列 ID,無論找到的物件是什么型別)。
In this case, git branch test001 v2.6.0-rc3 or git checkout -b test001 v2.6.0-rc3 has the same effect internally as you'd get using v2.6.0-rc3^{commit} with git rev-parse.
These syntax tricks work with most Git commands: wherever some hash ID might be required, you can use a name, and whatever name you supply goes through the same process git rev-parse uses to turn it into a hash ID.
1Annotated tags can be made to point directly tree or blob objects. If you do this, you cannot use them to create a new branch name. Annotated tag objects may also contain, as their target hash ID, the hash ID of another annotated tag object; in this case, Git continues indirecting until it finds the final object. This repeated indirection is called peeling tags, with the concept taken from the idea of peeling an onion, layer by layer, until you find out what is inside. Of course, in the case of an onion, when you've peeled away all the layers, there is nothing left but the smell. ??
2The exceptions here include:
git rebaseuses this mode deliberately to build a new commit chain. Once done,git rebaseforces the to-be-rebased branch name to point to the last of the new commits.If you like, you can work in this mode for a while, then create a new branch name yourself, or force some existing branch name to point to the new commit.
If you do work in detached-HEAD mode by mistake, you can use
git reflogto find the commit you want and create a branch name (or tag name!) that finds it.
Git mostly just provides the mechanism here, and you can build anything you like on top of that.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/332855.html
下一篇:致命:無法訪問“https://xxxx.git/”:服務器證書驗證失敗。CAfile:/etc/ssl/certs/ca-certificates.crtCRLfile:無
