2011-04-14 56 views
77

目前用於切換到另一個git的承諾(在同一分支上......實際上,在主分支!),我執行命令簽出一箇舊的提交併維護主分支上的頭部?

git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a 

現在,我每次做一次這個混帳告訴我,我現在擁有一個獨立的頭。我如何去一個較舊的提交,並仍然保持頭部在同一分支?

+1

執行該命令後,您的HEAD ref會更改爲* that * commit。希望HEAD也指向其他地方是沒有意義的。 – 2011-04-14 04:01:42

+0

從我從git的消息中瞭解到,它指向*無處*,這是不可取的。 – 2011-04-14 04:19:09

+1

當你簽出一個特定的提交,如「HEAD現在處於ea3d5ed ...」時,Git會顯示消息,它告訴你HEAD * *指向某處。它只是指向沒有任何其他名稱的地方* HEAD(除此之外,因爲對另一個提交或分支名稱的「git checkout」會將HEAD移動到新位置)。 – 2011-04-14 05:05:22

回答

177

很多時候我做到這一點我結賬到一個臨時分支時間:

git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a 

然後,我做我只是刪除分支

74

這取決於你想要做什麼時後你簽出提交。如果你所做的只是檢查它,所以你可以構建或測試該修訂版,那麼使用分離的頭部就沒有問題。請記住在進行任何提交之前(例如,git checkout master)檢出實際的分支,以便不創建任何未包含在任何分支中的提交。

但是,如果您希望從該點開始進行更多提交,則應該創建一個分支。如果你提交沒有被分支引用的提交,他們可能很容易丟失,並且最終會被git的垃圾回收器清除,因爲沒有任何引用它們。您可以通過運行創建一個新的分支:

git checkout -b newbranch ea3d5ed 

爲了幫助可視化,這裏的一些圖表顯示出從一個分支工作如何在一個分離的頭的工作不同。

讓我們先用3個提交上master,A,B和C. master是當前分支,所以HEADmaster,這點承諾C.

 
A B C 
*--*--* <-- master <-- HEAD 

現在,如果我們承諾, git會創建一個以C作爲父項的提交(因爲這是當前提交,通過master指向HEAD),並且將更新master以指向新提交。我們所有的提交現在都在masterHEAD指向通過master的新提交。

 
A B C D 
*--*--*--* <-- master <-- HEAD 

現在我們來看看B,給我們一個獨立的HEAD

 
A B C D 
*--*--*--* <-- master 
^
    \-- HEAD 

在這裏的一切工作正常;我們可以查看所有文件,構建我們的程序,測試它等。我們甚至可以創建新的提交;但是如果我們這樣做了,那麼就沒有分支,所以我們不能指出任何分支在新的提交。唯一指向它是HEAD

 
A B C D 
*--*--*--* <-- master 
    \ 
    * <-- HEAD 
    E 

如果後來我們決定再次檢查master,會有什麼參照E.

 
A B C D 
*--*--*--* <-- master <-- HEAD 
    \ 
    * 
    E 

由於沒有什麼提到它,它可以很難找到,git認爲提交沒有引用被放棄(如果你重新綁定或壓縮補丁,或者做其他有趣的歷史操作,它們通常會發生,通常它們代表你不再關心的已棄用補丁)。經過一段時間後,git會認爲它是垃圾,下次垃圾收集運行時將被丟棄。

因此,如果您覺得您要進行更多提交,您應該使用git checkout -b branch B創建分支並檢查出來,而不是檢查裸版本並獲得分離的頭部。現在您的提交不會丟失,因爲它們將包含在分支中,您可以輕鬆地引用它,並在稍後進行合併。

 
A B C D 
*--*--*--* <-- master 
^
    \-- branch <-- HEAD 

如果你忘了這麼做,並且創建了一個關閉分支的提交,沒有必要擔心。您可以使用git checkout -b branch創建一個指向首版修訂版的分支。如果您已經切換回master分支,並意識到您忘記了流浪提交,您可以使用git reflog找到它,它會顯示過去幾天提交HEAD提交的內容的歷史記錄。任何仍然在reflog中的東西都不會被垃圾收集,並且通常引用會保存在reflog中至少30天。

+0

這並不完全清楚爲什麼當你簽出一箇舊的提交時,頭部被分離*。也許問題在於什麼* detached *頭意味着什麼?另一方面,如果檢查一個獨立頭的舊提交只會丟失,爲什麼有人會這樣做?只是亂七八糟,試一下吧?爲什麼git首先允許它? – 2011-04-14 18:27:21

+5

@devoured elysium「detached head」意味着你有一個直接指向提交SHA-1的'HEAD' ref,而不是指向一個分支,該分支又指向一個提交。因爲你的頭沒有引用分支,所以當你添加新的提交時,Git不知道要更新哪個分支。正如我在我的回答開頭解釋的那樣,如果你要回到舊版本來構建或測試代碼,那麼擁有一個獨立的頭部是完全正確的;你總是可以用'git checkout master'或類似的東西回到分支。如果你在分離頭部的時候犯下這個問題,那只是一個問題。 – 2011-04-14 18:37:06

+0

@BrianCampbell - 在分支上提交(你的頭在哪裏)之後,你是否將分支合併到B中,並將B合併到master中。接下來你應該做什麼? – amey1908 2014-03-27 20:23:19

4

Git的HEAD只是一個指針,表示工作目錄中的內容。如果你想檢查一個不是分支頭部的提交,你只需要重定向你的HEAD指向那個提交。沒有辦法繞過它。您可以在該提交中創建一個臨時分支,但HEAD將被引導離開主設備。

這就是簡短的解釋。冗長下面將有望幫助理解HEAD和掌握如何不同:

通常情況下,事情是這樣的:

C ← refs/heads/master ← HEAD 
↓ 
B 
↓ 
A 

這就是說:「C的父母是B,和父B是A.分支主人指向C,我目前已經檢出了主人的內容。另外,當我提交時,主服務器應該被更新。「

爲了徹底理解提交圖,必須隱含一些假設。也就是說,提交只涉及他們的父母,而分支的內容是那些可以通過父鏈接到達的提交(並且只有那些提交)。工作樹和索引的(未修改的)內容必須與由HEAD命名的提交(間接(「符號」)或直接(「分離」))相對應。

因此,如果你想簽出一箇舊的提交,HEAD必須更新指向所需的提交。 git-checkout做到了這一點:

C ← refs/heads/master 
↓ 
B ← HEAD 
↓ 
A 

現在,你已經將你留下你的分支,因爲你在找什麼東西了。這是完全確定,爲「分離的頭」的建議告訴你從容(重點煤礦):

你可以環顧四周,使實驗變更並提交他們,你可以拋棄你在這種狀態下使沒有任何承諾通過執行另一次結賬來影響任何分支機構

另一方面,雖然重置您的分支也得到HEAD它需要的地方,它會有一個非常不同的效果!

C 
↓ 
B ← refs/heads/master ← HEAD 
↓ 
A 

提交C將變成垃圾,因爲你已經聲明你不希望它成爲主分支的一部分了。

簡而言之,你所要做的就是理解git的意思是「HEAD」 - 它就是所在的地方,而不是任何給定分支所在的地方。如果與分支所在的地方不一樣,那麼除了使用分離的HEAD之外別無選擇。

(也許還考慮GitHub上,gitk,或者叫做gitweb瀏覽提交歷史,如果出軌你的頭繼續激怒你。)

0

我想我明白你的問題。這是我發現解決它的。並沒有GUI解決方案,你只能用命令來解決它,而且非常簡單。

第1步:創建您想要返回的舊提交的標記。

像標籤2.0

第2步:git的結帳V2.0

這,現在你的頭指向「V2.0」提交,但主仍然是指向以最後一次提交。

C:\Program Files\Git\doc\git\html\git-checkout.html本文檔可以幫助你

或輸入git幫助<結賬>

7

如果你只是想返回到先前承諾發揮它而不做任何改變,你可以做

git co <previous-commit-id> 

你會在這個命令後面的一個叫「(no branch)」的分支上。

確認由

git br 

你這個承諾以前玩過的代碼後,你可以切換到您

git co <the-branch-you-were-on> 

的「(無分支)」分別對分行將自動刪除。這樣你就不需要創建一個臨時分支。

1

的問題是有點模糊,但如果你只想改變你的工作樹中的文件,你可以簡單地這樣做:

git checkout [commit|branch] -- .

然後,您可以階段的變化,並創建一個新的提交如果你希望。有時候這很有用。

相關問題