Git rebase loses history, then why rebase?
在过去的几天里,我一直在寻找与Git的重新平衡。大多数关于重新平衡的论据都说,它清理了历史,使其更具线性。如果你做了简单的合并(例如),你会得到一个历史记录,它显示了历史什么时候发生了分歧,什么时候又回到了一起。据我所知,重新平衡消除了所有的历史。问题是:为什么您不希望回购历史记录反映代码开发的所有方式,包括代码在哪里和如何分散?
想象一下你正在进行一个秘密的世界控制项目。这个阴谋有三个主谋:
- 天才
- 将军
- 电脑黑客
他们都同意在一周内到达他们的秘密基地,每个秘密基地都有一个详细的计划。
计算机黑客,作为一个务实的程序员,建议他们使用git来存储计划的所有文件。每一个都将用于最初的项目回购,它们将在一周内全部合并。
他们都同意,在接下来的日子里,事情是这样的:
天才
他总共做出了70次承诺,每天10次。
将军
他监视他们的同志们的反应,制定了一个击败他们的策略。他在最后一天做了3次承诺。
电脑黑客
这个务实的程序员使用分支。他做了4个不同的计划,每个计划都在一个分支上。每个分支都被重新设置为只提交一次。
七天过去了,小组再次开会,把所有的计划合并成一个主要部分。他们都急于开始,所以他们都试图自己合并所有的东西。
故事如下:
天才
他合并了将军回购协议的所有变更,然后是计算机黑客回购协议。然后,作为一个逻辑爱好者,他看了看日志。他期望看到一个想法的逻辑演变,在这个过程中,事物是建立在先前的想法之上的。
但是日志显示,在时间线上混杂着无数不同想法的投入。一个读者不能真正理解提交的演进,仅仅通过读取提交时间线就可以理解提交的推理。
所以他以一团糟而告终,连天才都无法理解。
将军
总的思想是:分而治之!
所以他把天才的回购协议合并到他的回购协议上。他看了看日志,看到了一堆天才想法的承诺,这是一个不可理解的进展,直到最后一天。最后一天,将军和天才的想法是混合在一起的。
他在监视电脑黑客,知道如何使用REBASE解决方案。所以,他重新考虑了自己的想法,并再次尝试合并。
现在日志显示了每天的逻辑进展。
电脑黑客
这个务实的程序员为天才的想法创建了一个集成分支,另一个是一般的想法,另一个是他自己的想法。他对每一根树枝都做了加固。然后他把所有的东西都合并成了大师。
他所有的队友都知道他的记录很棒。这很简单。一眼就能看得出来。
如果一个想法引入了一个问题,那么很明显是在哪个提交中引入的,因为只有一个提交。
他们最终征服了整个世界,他们也不再使用颠覆。
所有人都很高兴。
As far as I can tell, rebasing removes all that history.
号
那不正确。顾名思义,重新平衡会更改提交的基础。通常在这个过程中不会丢失提交(除非您没有获得合并提交)。虽然您关于将开发过程的所有内容都保持在历史中的做法是正确的,但这通常会导致混淆历史。
尤其是当与其他人一起工作时,每个人都在自己的分支上工作,同时要求其他人继续进行某些更改(例如,A要求B实现一些东西,以便A可以在自己的开发中使用该特性),这会导致许多合并。例如:
1 2 3 | #--#--#--#--*-----*-----------------*---#---\ Branch B / / / / \ ---#-----#-----#-----#-----#-----#-----#-----#-----* Branch A |
在这个例子中,我们有一个分支,它在一段时间内独立工作,但不断地从原始分支中提取更改(是原始提交,*是合并)。
现在,如果我们在重新合并之前在分支B上执行一个REBASE,我们可以得到以下结果:
1 2 3 | #--#--#--#--#---\ Branch B / \ ---#---#---#---#---#---#---#---#---------------* Branch A |
号
这表示相同的实际更改,但B在A上重新设置为某些较旧的提交,因此不再需要B上以前完成的所有合并(因为这些更改已经存在于较旧的提交中)。现在丢失的所有提交都是合并,通常不包含任何有关开发过程的信息。(注意,在这个示例中,您还可以重新设置最后一次提交的时间,以获得一条直线,有效地删除第二个分支的任何提示)
您主要在远程分支(您只是获取)的顶部重新编写本地提交(您尚未推送的提交),以便在本地解决任何冲突(即,在将它们推回到上游回购之前)。请参阅"Git工作流和Rebase与合并问题",以及非常详细的"Git Rebase与Git合并"。
但是Rebase并不局限于这种情况,它结合了"—交互式",允许对您的历史进行局部重新排序和清理。另请参见"剪裁Git签入/挤压Git历史记录"。
why wouldn't you want the repo history to reflect all the ways the code developed, including where and how it diverged
号
- 在一个集中的VCS中,永远不要丢失历史是很重要的,它确实应该反映"代码开发的所有方式"。
- 在分布式VCS中,您可以在向上游发布某些分支之前进行所有类型的本地实验,将所有内容保留在历史中没有什么意义:不是每个人都需要克隆并查看所有分支、测试、备选方案等等。
如果您在公共存储库上犯了错误,但还没有人从中分叉/合并/提取,那么您可以省去面子和困惑:
1 2 3 4 5 | git reset --hard [SHAnumber] git rebase -f master git push -f origin HEAD:master |
清空垃圾:
1 | git gc |
号