2010-04-10 136 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管理员仍然可以删除选定的提交。

相关问题