2010-04-10 135 views
130

來自svn,剛開始熟悉git。在git中刪除分支是否將其從歷史記錄中刪除?

當一個分支在git中被刪除時,它是否從歷史中刪除?

在svn中,您可以通過恢復刪除操作(反向合併)輕鬆恢復分支。像svn中的所有刪除一樣,該分支從不真正刪除,它只是從當前樹中刪除。

如果該分支實際上從git中的歷史中刪除,那麼從該分支合併的更改會發生什麼?他們保留了嗎?

回答

176

分支只是提交git的指針。在git中,每個提交都有一個完整的源代碼樹,它與svn有着非常不同的結構,其中所有分支和標籤(按照慣例)與特殊的「trunk」一起位於存儲庫的單獨「文件夾」中。

如果分支在被刪除之前被合併到另一個分支,那麼當第一個分支被刪除時,所有提交仍然可以從另一個分支到達。他們保持完全一樣。

如果分支被刪除而未被合併到另一個分支中,那麼該分支中的提交(直到從仍然可達的提交分出的點)將不再可見。

提交仍將保留在存儲庫中,並且可以在刪除後立即恢復它們,但最終它們將被垃圾收集。

+2

感謝您的回答。你能否澄清你的意思是「每個提交都有一個完整的源代碼樹」?據我瞭解,git中的每個提交都是一組引用父代提交的增量,而不是整個樹。 – 2010-04-10 23:25:43

+0

不是,每個提交都是給定點上樹的狀態。增量值只在稍後計算,用於顯示和重新綁定以及什麼,但提交ID是整個樹的哈希值。 – ben 2010-04-10 23:27:09

+1

@Ken Liu:一個提交包含指向零個或多個父提交的指針,一個樹對象和一些關於提交的元數據。因此,提交可以唯一地標識一對數據源樹,並且在對其父代進行查看時,可以唯一標識它所引入的更改。 – 2010-04-10 23:38:25

62

在Git中,分支只是在提交的有向無環圖(DAG)中提交的指針(引用)。這意味着刪除分支只會刪除對提交的引用,這可能會導致DAG中的某些提交無法訪問,從而不可見。但是,刪除分支上的所有提交仍將存儲在存儲庫中,至少在不可恢復的提交被修剪之前(例如使用git gc)。

請注意,git branch -d會拒絕刪除分支,如果它不能確定刪除它將不會留下不可達的提交。您需要使用更強大的git branch -D強制刪除分支,如果它可能會導致無法訪問的提交。

還要注意,無法訪問的提交(如果存在)只是已刪除分支的最後一個提示與已合併到另一個現有分支的提交,任何已標記的提交或分支點之間的提交;以後到者爲準。例如在以下情況下:

 
----O----*----*----/M----* <-- master <-- HEAD 
    \   /
     \--.----.--/--x---y  <-- deleted branch 

只有提交'x'和'y'在刪除分支後將變得無法訪問。

如果您在gc.reflogExpire期限內對已刪除的分支操作,缺省的90天,你就必須記錄在HEAD引用日誌刪除分支的最後一個技巧(見git reflog show HEAD,或git log --oneline --walk-reflogs HEAD)。您應該能夠使用HEAD reflog來恢復已刪除的指針。還要注意的是,在這種情況下,只有被刪除的分支中的不可訪問的提交將被保護免於在gc.reflogExpireUnreachable期間內的修剪(移除),默認爲30天。

如果你不能找到引用日誌的頭剛剛刪除分支的頂端,你可以嘗試使用git fsck找到「不可達提交<SHA1>」,並檢查那些(通過git show <sha1>git log <sha1>)找到已刪除分支的提示。

獨立你如何找到已刪除的分支的末端,您可以撤消刪除,或者更確切地說,重新創建使用

git branch <deleted-branch> <found-sha1-id> 

然而要注意引用日誌的分支將失去一個剛剛刪除的分支。


也有在contrib/git-resurrect.sh腳本,這有助於找到一個分支的頂端具有給定名稱的痕跡和復活(撤消刪除)它。

+0

太棒了! 'git reflog show HEAD'列出了提交,並且我創建了一個新的分支,就像您所說的那樣完美。 – 2015-01-29 23:46:43

1

如果您擔心意外刪除了分支機構,並且沒有本地副本,那麼可以使用像Gerrit這樣的企業Git服務器擴展程序來檢測歷史重寫和分支刪除,並將其備份到特殊以便在需要時可以恢復它們,並且不會被垃圾回收修剪。出於法律原因,Gerrit管理員仍然可以刪除選定的提交。

相關問題