Git重新设定会丢失历史记录,然后为什么重新设定?

问题描述 投票:50回答:5

在过去的几天里,我一直在考虑与Git进行重新定位。关于重新定基的大多数论点都说,它可以清理历史并使其更加线性。如果进行简单合并(例如),则将获得一个历史记录,该历史记录将显示历史记录何时发生分歧以及何时将其重新组合在一起。据我所知,重新定基会删除所有这些历史记录。问题是这样的:您为什么不希望回购历史记录反映代码开发的所有方式,包括代码在哪里以及如何分开?

git version-control git-rebase git-merge
5个回答
30
投票

据我所知,重新定基会删除所有历史记录。

这是不正确的。顾名思义,重定基会更改提交的base。通常在该过程中不会丢失任何提交(除非您没有获得合并提交)。尽管您关于将开发过程的所有内容真正保留在历史记录中的说法是正确的,但通常这会导致混乱的历史记录。

特别是当与其他人一起工作时,每个人都在自己的分支上工作,而要求其他人的某些改变以继续(例如,A要求B实现某些东西,以便A可以在自己的开发中使用该功能),这导致许多合并。例如这样:

     #--#--#--#--*-----*-----------------*---#---\         Branch B
    /           /     /                 /         \
---#-----#-----#-----#-----#-----#-----#-----#-----*       Branch A

在此示例中,我们有一个分支,该分支目前可以单独工作,但是会不断从原始分支中提取更改(#是原始提交,*是合并)。

现在,如果我们在合并回去之前在Branch B上进行重新定位,我们将获得以下信息:

                             #--#--#--#--#---\         Branch B
                            /                 \
---#---#---#---#---#---#---#---#---------------*       Branch A

这表示相同的实际更改,但是B重新基于对A的一些较早的提交,因此不再需要对B进行的所有合并(因为这些更改已经存在于较早的提交中)。现在所有丢失的提交都是合并,通常不包含有关开发过程的任何信息。 (请注意,在此示例中,您也可以稍后将最后一次提交基于A,以获得一条直线,从而有效地删除对第二个分支的任何提示)


60
投票

想象您正在从事一项世界统治的秘密项目。这个阴谋有三个策划者:

  • 天才
  • 将军
  • 计算机黑客

并且他们都同意在每个星期内提供一个详细计划,并在1周内进入他们的秘密基地。

计算机黑客是一个务实的程序员,建议他们使用Git存储计划的所有文件。每个人都会分叉最初的项目存储库,它们将在一周内全部合并。

他们都同意,在接下来的日子里,故事是这样的:

天才

他总共进行了70次提交,每天10次。

The General

他监视同志的回购,并制定了击败他们的策略。最后一天他做了3次提交。

计算机黑客

这位务实的程序员使用分支。他制定了4个不同的计划,每个计划都在一个分支上。每个分支都重新设置为仅一次提交。

经过了7天,小组再次开会,将所有计划合并为一个大师作品。他们所有人都渴望开始,所以他们所有人都试图自己合并所有内容。

这里是故事:

天才

他合并了将军仓库中的所有更改,然后合并了计算机黑客的所有更改。然后,作为一个逻辑爱好者,他看了一下日志。他希望看到一个想法的逻辑演变,其中事物是基于先前的想法-提交构建的。

但是记录显示的是,在时间表中混杂了无数种不同的想法。一位读者仅通过阅读提交时间轴就无法真正理解其演变,提交的理由。

所以他以混乱结束,即使是一个天才也无法理解。

The General

一般思想:分而治之!

于是他将Genius的回购合并到他的回购中。他看了看日志,看到了来自Genius想法的一堆提交,随后进展缓慢,直到最后一天。最后一天,将军和天才的想法混杂在一起。

他在监视计算机黑客,并了解Rebase解决方案。因此,他重新调整了自己的想法,然后再次尝试合并。

现在日志每天都显示出合理的进展。

计算机黑客

这位务实的程序员为Genius想法创建了一个集成分支,为General想法创建了一个分支,为他自己的想法创建了一个分支。他对每个分支机构进行了调整。然后他将所有内容合并为主人。

他的所有队友都看到他的日志很棒。很简单。一见钟情,情况很不稳定。

[如果一个想法引入了一个问题,那么很明显,引入了哪个提交,因为只有一个。

他们结束了征服世界,并取消了Subversion的使用。

所有人都很高兴。


12
投票

您进行重新设置主要是为了在远程分支(您刚刚获取)上重做本地提交(您尚未推送的提交),以便解决任何冲突[(即,在推送之前他们回到上游仓库)。请参阅“ git workflow and rebase vs merge questions”,以及非常详细的内容:“ git rebase vs git merge”。

但是,重新定位不仅限于这种情况,并且与“ --interactive”结合使用,它可以对本地历史记录进行一些重新排序和清理。另请参见“ Trimming GIT Checkins/Squashing GIT History”。

您为什么不希望回购历史记录反映代码开发的所有方式,包括代码在哪里和如何分开

    在集中式VCS中,重要的是永远不要丢失历史记录,它确实应该反映“代码开发的所有方式”。
  • 在分布式VCS中,您可以在
  • publishing某些分支上游之前进行各种本地实验,将everything
保留在历史记录中是没有意义的:并非所有人都需要克隆并查看您的所有分支,测试,替代方案,等等。

0
投票
如果您在公共存储库上犯了一个错误,但尚未有人分叉/合并/拉出它,则可以避免面子和混乱:

git reset --hard [SHAnumber] git rebase -f master git push -f origin HEAD:master

要清空垃圾箱:

git gc


0
投票
整理您的历史记录是在合并中使用rebase,这是非常有价值的。

git历史记录有什么用,它可以准确反映过去的每个代码更改?您需要某种东西来进行某种认证吗?如果不这样做,为什么要这样?真实发生的过去是混乱且难以理解的。我的意思是,为什么不还包括您在编辑文件时写的然后删除的每个字符?

您将使用git历史记录的最常见方法是阅读它。查找哪个提交引起了问题并浏览文件的不同版本可能是两个最常见的用例。当您的git历史记录很简单(并且很干净!)时,这两个用例都变得更加简单和方便。

也许比使用rebase与团队的其他成员共享更改更为重要,每个成员都应使用rebase将其更改格式化为独立的提交的逻辑集合。开发并非自然而然地发生在彼此直接遵循的逻辑步骤中。有时候,您只是因为一天结束而只在分支上推动提交,所以您必须走了。将此类信息放入您的git历史记录中纯属噪音。我通常会压缩一项功能,该功能将20次提交减少到一两次,因为毫无意义地显示出最终没有成为成品的一部分。

即使您的功能的开发历史是一团糟,您也可以并且绝对应该制作一个通用的git历史。您第一次以正确的顺序正确处理了所有事情,在第一天就完成了功能A,在第二天就完成了功能B,没有错误或临时打印语句。你为什么要那样做?因为对于阅读您的更改的人来说更容易理解。

如果将此思想与git bisect结合使用,那么整理您的主历史记录,使其仅包含通过当时定义的所有测试的提交,将更加有用。因为git bisect会起作用,所以找到bug的起点很简单。如果您使用merge并将每个分支的整个开发历史记录上载到master,那么bisect实际上没有帮助的机会。

© www.soinside.com 2019 - 2024. All rights reserved.