[英]Detached HEAD on same commit as main?
我不太確定在這種情況下我是如何獲得我的存儲庫的,這甚至不再是一個問題,但我想了解發生了什么,所以下次我不會感到如此迷茫。
拉動時,我被警告說我處於分離的 HEAD 狀態。 git status
顯示如下(截圖):
HEAD detached at 44422b7
所以我跑了git log
來找出我離 main 有多遠,它顯示了(截圖):
commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD, main)
這對我來說沒有多大意義,因為我似乎與主分支在同一個提交中,但是為了解決問題,我運行了git checkout main
,然后顯示下一個git log
(截圖),
commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD -> main)
一切都開始按照我最初的預期工作。
所以我試圖理解git log
在我第一次和第二次運行它時顯示的區別(帶有箭頭的那個與只有一個逗號的那個),也許了解我是如何遇到這種情況的第一名。
感謝我能得到的任何幫助。
分支是指向提交的標簽。
HEAD 總是指向當前簽出的提交。
commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD, main)
commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD -> main)
兩者都說你在提交 44422b74b6826291479ee7a17fe18bb4acca6355。 兩者都說 HEAD 和該提交的要點。 但是HEAD -> main
說 main 是當前簽出的分支。
當您運行git commit
時,會創建一個新的提交,並且當前簽出的分支和 HEAD 會被移至它。
可能沒有簽出分支,這是一個分離的 HEAD 狀態。 在這種情況下,當你git commit
只有 HEAD 移動。 沒有分支正在跟蹤您的提交。 如果你git checkout
或git switch
away,將(幾乎)沒有任何東西提到那些分離的提交。
有很多方法可以進入分離的 HEAD 狀態,最基本的是檢查提交 ID。 git checkout 4ba97c6ffc71f88a4de4ed88b188dbec2e5ff325
。
您可以通過檢查分支來擺脫分離的 HEAD 狀態,就像您所做的那樣。 或者你可以在你所在的地方建立一個新的分支。
確保使用git switch main
,而不是git checkout main
。
通過使用git switch
,您可以降低以分離的 HEAD結尾的風險,因為您會收到錯誤消息(切換到提交或遠程分支時)
fatal: a branch is expected, got remote branch 'origin/master'
您需要顯式添加--detach
選項才能得到一個分離的 HEAD。
這實際上是兩個獨立的問題:
試圖了解 git log 在我第一次和第二次運行它時顯示的內容之間的區別(帶有箭頭的那個與只有一個逗號的那個),
首先要了解我是如何陷入這種境地的。
問題 2 的答案是為什么我的 Git 存儲庫進入了分離的 HEAD 狀態?
問題 1 的答案更簡單:第一個顯示 detached-HEAD 狀態,第二個帶有箭頭的顯示attached-HEAD 狀態。 但是我們可以稍微解釋一下:特別是“分離 HEAD”的整個概念首先有點奇特。 不過,在我們描述它之前,我們必須知道附加的 HEAD 是什么! 從某種意義上說,它是顯而易見的——它與分離的 HEAD 相反——但這只是循環推理。 我們需要一些更基本的東西,這在於Git 如何找到提交。
首先,請記住每個 Git 提交都有一個唯一的哈希 ID:
commit 44422b74b6826291479ee7a17fe18bb4acca6355
那一大串難看的字母和數字是一個數字,用十六進制表示。 (十進制是 389687007142770230305517186390235637298437448533,這實際上並沒有更好。😀事實上,Git 必須使用十六進制或二進制,因為它在數據庫中通過前綴查找這些信息的方式,部分使用了各種大小的 2 次冪。)此哈希 ID 用作簡單鍵值數據庫中的鍵; 該值是提交的內部 Git 表示。
所以 Git需要這個提交哈希 ID 才能找到這個提交。 您必須為 Git 提供哈希 ID:這是 Git 查找提交的唯一方法。 但是誰想一遍又一遍地輸入44422b74b6826291479ee7a17fe18bb4acca6355
呢? 你甚至會做對嗎? 如果你可以只說main
並且 Git 可以在輔助鍵值存儲中查找main
——或者,技術上, refs/heads/main
——並找到44422b74b6826291479ee7a17fe18bb4acca6355
怎么辦? 那不是更好嗎?
是的,它實際上更好,這就是我們所做的:我們輸入main
或v1.2
或origin/develop
,Git 在這個輔助數據庫中查找它以獲取原始哈希 ID。 從那里,Git 找到我們想要的提交。
當您“在分支上”時,正如git status
所說,這意味着您所做的每個新提交都會更新當前分支名稱。 因此,如果您on branch main
並且您進行了新的提交並且其哈希 ID 為a123456...
或其他任何內容,Git 將存儲新提交的哈希 ID a123456...
或其他名稱,名稱為main
。 (舊的 commit-hash-ID 44422b74b6826291479ee7a17fe18bb4acca6355
- 進入新的提交,因此它現在是倒數第二個提交。)
反過來,這意味着 Git 需要始終知道哪個分支名稱是它應該在您進行新提交時更新的名稱。 為了記住該分支名稱,Git 將特殊名稱HEAD
“附加”到分支名稱。
(當前的實現是 Git 將ref: refs/heads/main
寫入.git/HEAD
。但是,這個實現在未來可能會發生變化。當前的實現已經與之前的不同,並且已經有所改變處理添加的工作樹,因為現在它有時根本不是.git/HEAD
:那只是用於主工作樹。)
附加的 HEAD是指 HEAD 包含分支的名稱。 HEAD 中包含的分支名稱是當前分支。 分支名稱本身,在充滿名稱到哈希 ID 映射的數據庫中,包含當前提交的哈希 ID。 所以HEAD
提供了兩條信息:
要分離HEAD,Git 只需將某個提交(任何現有提交)的原始哈希 ID 寫入HEAD
。 現在.git/HEAD
包含一個原始哈希 ID,沒有當前分支名稱,但仍然有一個當前提交哈希 ID 。 只是HEAD
現在直接持有了。 無需在名稱數據庫中查找名稱。
你所做的一切仍然和以前一樣工作:特別是,如果你創建一個新的提交,新的提交會連接(向后,就像提交一樣)到你創建新提交時的當前提交; 現在新的提交就是當前的提交,即 Git 已將其哈希 ID 存儲在HEAD
中。
如果您確實進行了這樣的提交並運行git log
,您將看到:
commit a123456... (HEAD)
[your new commit]
commit 44422b74b6826291479ee7a17fe18bb4acca6355 (main)
[your old commit]
由於git log
從當前提交開始並向后工作,因此一次提交一個。 但是由於您沒有創建新的,因此名稱HEAD
和名稱main
均表示“提交 44422b74b6826291479ee7a17fe18bb4acca6355”,因此您得到:
commit 44422b74b6826291479ee7a17fe18bb4acca6355 (HEAD, main)
附加HEAD
后,Git 會使用該向前箭頭符號打印它(因為 Git 2.10:在 2.10.0 之前,Git 打印HEAD, main
兩種情況)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.