Git Rebasing是否会改变提交树

时间:2016-10-12 20:40:43

标签: git rebase

我看到了这个非常可靠的教程,该教程表示,仅使用不同的SHA键进行新的提交只会因为它所指向的父级现在不同而其他所有内容都相同。

然而,如果这是真的并且没有其他任何改变,那么如果我们通过向下钻入其根树来遍历最新的重新提交的提交,它的子树和blob将不会与原始的重新生成树相同吗?

根据定义,最新的重新定位的提交树是否包含来自主分支和重定位分支的内容的并集?在这种情况下,提交应该指向一个新的根树结构,它具有新的子树,blob和可能的新节点添加,无论是子树还是更多的blob。

3 个答案:

答案 0 :(得分:3)

如果没有类似教程本身的链接,就无法说出它是否错误,或者你只是holding it wrong。 :-)但是,rebase在内部工作,就好像通过一系列git cherry-pick操作一样。

事实上,交互式rebase实际上运行git cherry-pick。非交互式rebase使用git format-patchgit am代替,但可以。

默认情况下,两个rebase都会尝试不复制不需要复制的提交。也就是说,如果某个待复制提交的目标(在应用先前提交之后内部计算和/或来自--onto参数,如果有的话)是同一个父提交已经有了,底层的rebase可以简单地快进正在进行的新匿名分支,而不是复制它。在这种情况下,SHA1都保持不受干扰。您可以使用-f--force-rebase--no-ff明确禁用此行为。只要新副本上的时间戳不同,它就会获得不同的SHA1哈希值(即使/尽管其他所有内容都相同)。

在内部,目标只是HEAD,因为rebase通过使用分离的HEAD模式在内部工作。当每个旧提交被复制到新提交时,Git只需要像往常一样进行新提交(或者对于那个特例,使用git reset向前迈步)。

一般情况下,只要某事已经改变 - 如果父ID已经改变(即目标不同),这肯定是正确的 - -Git必须构造一个新的提交。实际上,它将原始提交应用为当前提交的补丁。

请注意,此无法用于合并提交,这不能表示为单个补丁。 1 因此,git rebase通常剥离out 完全合并提交。交互式rebase脚本的代码为"保留"合并,但它实际上不能保留合并(特殊的快进案例除外):相反,它必须重新执行合并,以及所做的所有后果如此。

1 合并提交可以由至少两个补丁表示,一个针对第一个父节点,另一个针对每个其他父节点,但不仅仅是一个。但是,这样的表示对于我们的目的来说是无用的:--preserve-merges旨在将合并移植到一个新的提交链中,具有不同的起始代码库,因此我们可以预期差异对第二个(以及任何其他)父母要改变。

答案 1 :(得分:1)

Git为提交创建新的SHA ID,以及树中的所有元数据,如blob。你说内容是一样的是正确的,但是所有的IDS都完全改变了。

答案 2 :(得分:0)

关键是git像链表一样实现!因此,当您丢失链接时,无法追踪它。

集成分支的最简单方法是merge命令。它在两个最新的分支快照之间执行三向合并,创建新的快照(和提交)。

enter image description here

但是,在rebase中,您可以获取更改的补丁并将其重新应用于主分支。

enter image description here

您可以在这里阅读更多内容:

  

https://git-scm.com/book/en/v2/Git-Branching-Rebasing

我希望它有所帮助;)