化石:rebase被认为有害

2021-02-24 21:32:46

化石故意省略A" rebase"命令是因为化石的原始设计器(和本文的原始作者)考虑了rebase作为要避免的反模式。本文试图批准该观点。

大多数人,即使是rebase的尖锐倡导者,也同意在误用时恢复撤销问题。 git rebase文档谈论重建的黄金法则:从不在publicbranch上rebase。令人滥计绑定的恐怖故事比比皆是,rebase文档致力于解释rebase错误和/或滥用的扭转。

有时夏普和危险的工具是合理的,因为他们完成了无法替代的事情,或者至少不能轻易完成.Rebase不会陷入该类别,因为它没有提供新功能。

一个rebase真的是一个合并(或一系列合并),故意忘记每个合并步骤的一个父母。要帮助说明此事实,请考虑来自GIT文档的第一个重新启动示例。合并看起来像这样:

scale = 0.8circle" c0"菲律艇右边50%圈子相同" c1" arrow samecircle相同" c2" arrow samecircle相同" c3" arrow samecircle相同" c5"圆形相同& #34; c4"从C2到C3的1cm以上C2至C4从C4到C5剁

scale = 0.8circle" c0"菲律艇右右50%圈相同" c1" arrow samecircle相同" c2" arrow samecircle相同" c3" arrow samecircle相同" c4'"&#34 ;圈子相同" c4"从C2到C4 Check以上1厘米

随着GIT文件指出,检查INS C4'和c5are相同。 C4&#39之间的唯一区别; C5是C5Records C4是其合并父母但C4'才不是。

Git文档承认了这个事实(用很多话),并说“重新建立基础可以使历史更清晰”。我读到这句话是默许的,它承认Git历史记录显示功能很弱,需要用户的积极协助以使事情易于管理。当然,更好的方法是记录每次签到的完整记录,然后将工具修复为显示&# 34; clean"简化显示既可取又诱人的情况下的历史记录,但对于细节和准确性更重要的情况,保留显示真实,完整,混乱的历史记录的选项。

因此,考虑重新设置的另一种方法是,这是一种合并,有意忘记一些细节以免淹没Git中可用的薄弱的历史显示机制。这样做会更好,更不易出错且更容易用户可以增强Git中的历史记录显示机制,从而不必为了获得清晰,线性的历史记录而重新建立基础?

经常被引用的另一种说法是,重新设置功能分支后,可以只查看功能分支中的更改而无需在开发主线中同时进行更改。考虑一个假设的情况:

比例= 0.8圈" C0"适合填充whitearrow右50%相同的圆圈" C1"箭头相同的圆圈相同" C2"箭头相同的圆圈相同" C4"箭头相同的圆圈相同" C6"圆圈相同的" C3"在最后一个arrow.width + C0.rad * 2从C2arrow向右30%的位置上将相同的" C5" arrow从C2到C3切碎框ht C3.y-C2.y wid C6.ex-C0.w C2后面的.x + 1.5 * C1.rad在C0后面填充0xc6e2ff颜色0xaac5dfbox ht previous.ht wid previous.wid * 0.55,在.se后面的\ se \ C0后面填充0x9accfc颜色0xaac5dftext" feature"在先前的.s中加上.s。ntext" main"在第一个box中使用.n

在上面,由签到C3和C5组成的功能分支与签到C4和C6中的主行同时运行。要求重新设置基础的人说,您应该将功能分支重新构建到main的顶端,以便消除功能分支历史中的主线开发差异:

#重复以下第5.0节= 0.8圈" C0"适合填充whitearrow右50%相同的圆圈" C1"箭头相同的圆圈相同" C2"箭头相同的圆圈相同" C4"箭头相同的圆圈相同" C6"圆圈相同的" C3"在最后一个arrow.width + C0.rad * 2处,从C2箭头向右30%将相同的" C5"箭头从C2到C3剁成圈C3P:圈出相同的" C3'"在第一个arrow.width + C0.rad * 2处,从C6arrow处向右30%从C3P.eC5P处:将相同的" C5'箭头从C6圈到C3P杂物箱ht C3.y-C2。 y wid C5P.ex-C0.w.x + 1.5 * C1.rad,.w在C0.w以西\ 0.5 *(第一个箭头.wid)\在C0后面填充0xc6e2ff颜色0xaac5dfbox ht previous.ht wid previous.ex- C2.wx在C0之前的.ne \后面有.se填充0x9accfc颜色0xaac5df

您可以选择折叠C3'和C5'合并到此基础的一个检查中,但这是一个附带问题,我们将单独处理。

因为化石有目的地缺乏rebase,所以最接近的你可以获得同样的检查是以下的融合:

scale = 0.8circle" c0"适合填充whitearrow右50%圈相同" c1" arrow samecircle相同" c2" arrow samecircle相同" c4" arrow samecircle相同" c6"圆形同一个" c3"在最后一个箭头.Width + C0.RAD * 2从C2Arrow向右30右圈50%圈相同" C5"箭头Samecircle相同" C7"从C2到C3从C6到C7 Chockbox的箭头ht c3.y-c2.y wid c7.ex-c0.w​​.x + 1.5 * c1.rad,with .w在0.5 *(第一个箭头.WID)的C0.W \后面C0填充0xC6E2FF颜色0xAC5DFBOX HT之前.ht wideguard.ex - c2.wx与.se在上一个.ne \后面c0填充0x9accfc颜色0xac5df

来自rebase advcateis的论点,它很难只看到没有被混合的主线更改的特征分支相关的更改。在其他单词中,diff(c2,c7)显示了FeatureBranch和来自主线的变化,而在Rebase CaseDiff(C6,C5')仅显示特征分支更改。

但该论点正在将苹果与橙子进行比较,因为这两个差异没有相同的基线。只有在合并案例中只看到FeatureBranch更改的正确方法不是差异(C2,C7),而是差异(C6,C7)。

记住:C7和C5'比特与位相同,因此无论您是选择C7还是C5&#39,都不确定C7或C5&#39的输出;作为差异的目标,而是通过您选择的差异,C2或C6。

因此,为了帮助查看与FeatureBranch相关联的更改的问题,也许是必要的不是rebase,而是更好的工具,以帮助用户确定其差异的适当基线。

Rebasing的黄金法则是你永远不应该做ITON公共分支机构,所以如果你正在使用预期的rebase,那么你正在保留私人分支机构。或者,把它放在另一种方式,你坐落在寂静的发展中。您不会分享您的中间工作。这对产品质量不利。

长庚等。 Al等人研究了Windows Vista中的错误,发现错误的最佳预测指标是利益相关者之间的组织结构图上的距离。错误率与工程师之间的交流数量成反比。在其他学科中也有类似的发现。保持私有分支并不能证明开发人员通信不足,但这是该问题的关键症状。

温伯格认为编程应该是“无我的”。就是说,程序员应该避免将代码与自身的感觉联系起来,因为这会使他们更难以发现和响应错误,从而降低他们的生产力。许多开发人员出于自我意识而被吸引到私人分支机构。 "我想在发布代码之前得到正确的代码。"我对此感同身受,并本人经常对此感到内。在一个永远不会忘记的互联网上向全世界展示您的愚蠢错误,真是令人感到羞耻。然而,谦虚的程序员会生成更好的代码。

固态代码最快的途径是什么?是继续盯着您的私有分支以查找每个最后的错误,还是发布它的原样,于是,许多人立即看到了代码中的最后一个愚蠢的错误?测试和开发通常由较大的软件开发组织中的独立小组完成,因为开发人员离自己的代码太近了,无法看到其中的每个问题。

鉴于此,让许多眼球在功能分支上仍然孤立的情况下找到您的问题比较好,还是应该等到最终将私有工作分支的折叠版本推到父仓库后再进行审核?当它们与实现某些引人注目的新功能的代码混合在一起时,会引起很多人的注意吗?

#放大2.2节中第二张图的副本= 0.8圈" C0"适合填充whitearrow右50%相同的圆圈" C1"箭头相同的圆圈相同" C2"箭头相同的圆圈相同" C4"箭头相同的圆圈相同" C6"圆圈相同的" C3"在最后一个arrow.width + C0.rad * 2处,从C2箭头向右30%将相同的" C5"箭头从C2到C3剁成圈C3P:圈出相同的" C3'"在第一个arrow.width + C0.rad * 2处,从C6arrow处向右30%从C3P.eC5P处:将相同的" C5'箭头从C6圈到C3P杂物箱ht C3.y-C2。 y wid C5P.ex-C0.w.x + 1.5 * C1.rad,.w在C0.w以西\ 0.5 *(第一个箭头.wid)\在C0后面填充0xc6e2ff颜色0xaac5dfbox ht previous.ht wid previous.ex- C2.wx在C0之前的.ne \后面有.se填充0x9accfc颜色0xaac5df

C3上的时间戳记是什么?和C5'签到?如果您选择与原始C3和C5相同的时间戳,那么您的情况就更奇特了C3'比其父级C6大。我们称其为“时间扭曲”。在化石。由于系统时钟配置错误,时间扭曲也会发生,因此它们不是唯一的基础,但它们非常混乱,因此最好避免。另一个选择是为C3'提供新的唯一时间戳。和C5'但是您会丢失有关最初创建这些签入的时间的信息,这会使历史记录更改分析变得更加困难。这也可能使现有技术要求的法律辩护复杂化。

通过丢弃育儿信息,变基尝试欺骗读者有关代码实际上是如何组合在一起的。

您可能会旨在将此视为化石网站的反盖特观点,但它在Git Rebasedocumentation中拼写出来。它谈到了“撒谎”,“讲述故事”和“亵渎”。

GIT文档的那段部分是对比具有合并的rebase,上面的Wecover,但Git的rebase功能不仅仅是合并的Analternative:它还提供了用于更改Project历史记录的机制以使编辑变化更改。化石表明,如果您可以在不修改历史记录的情况下获得类似的效果,允许用户:

化石允许通过删除或修改现有的申请条目,而是添加新的补充记录,而是通过添加新的补充记录.FOSSIL保持原始的错误或不明确的输入,并使其进行全面访问,保留原始的历史记录。 FOSSINDOSE不要让用户告诉反事实“故事”,它只允许众所周期以为要提供注释,以便为例行显示目的提供更可读的EDitedPresentation。

Git需要rebase,因为它缺乏这些注释设施。宁愿考虑rebase在化石中缺少一个缺少的理想特征,而不是为缺乏历史提供历史记录进行编辑变化的支持,而不是缺乏Git的支持? WORN' t更好地修复版本的控制台,而不是要求用户制作虚构的ProjectHistory?

在Git中重建的遗传优势之一是它让您可以将多次登记入住,以便单一登记入住,以使历史“清洁”。意图是,开发出现在一步中创建的每个功能都是:没有多层行进,没有背跟踪,没有假开始,没有错误。这种无知的开发人员心理学:思想很少从食物成品形式的手指Tofiles涌出。愿望崩溃,最终确定的挑战是反事实的愿望。

常见的反驳是折叠的核对者代表女儿世界,理想的我们'追求。那个论点忽略了我们必须扔掉有价值的信息来到达那里。

理想情况下,我们的软件的未来开发人员可以仅在他们启动的代码版本中使用的上下文了解它。在广泛的版本控制之前,开发人员没有选择这种方式。预先存在的Codebases只能理解 - 是或根本没有。那个世界的开发人员有一个令人振奋的开发软件,很容易追溯理解,即使是自私的人,因为他们知道他们最终可能会成为未来的开发人员!

但是,有时我们遇到一段我们根本无法理解的代码。如果您从未问过自己,"此代码的开发人员在想什么?您已经很长时间没有开发软件了。

当开发人员可以返回到当前代码的各个签到位置时,他们可以仅使用成为优秀开发人员所需要的个人才能来解决此类问题。为了仅使用完成的表单来理解此类代码,您要让未来的开发人员做出原开发人员无法进行的直观飞跃。换句话说,您是在要求将来的维护开发人员比原始开发人员更聪明!这是一个美丽的愿望,但是对携带的距离有一个严格的限制。最终,您达到了人类的光彩极限。

当一些代码的操作不明显时,Fossil和Git都可以让您对代码文件负责,以获取有关每一行代码的信息,以及从检入最后触及给定代码行的信息。如果将分支下的签入压缩为单个签入,则会丢弃导致该已完成表格的信息。 Fossil不仅保留了您尝试理解的代码行周围的签入内容,其出色的数据模型还使您可以从两个方向查看周围的签入内容;不仅是导致这种情况的原因,而且是接下来发生的事情。 Gitcan只需从分支的尖端向后爬行到要查看的签入位,这是一项昂贵的操作。

我们认为,从10行检入中理解其中的一行代码(然后根据需要理解周围的检入)要比理解500行检入会使整个折叠崩溃要容易得多。分支机构可以进行的更改只有一个完成功能。

Git允许开发人员在十个签入中编写功能,但将其折叠到第十一个签入,然后有意地仅将最终折叠的签入推送到父仓库。然后,其他人可能会进行二等分,将合并的签入归咎于他们正在解决的问题的根源;然后,他们必须手动计算出原始开发人员创建它所采取的10个步骤中的哪一个,以找到实际问题的根源。

对Fossil的等效推送将把所有11个签入都发送到父存储库,以便稍后进行相同类对分的调查人员可以查看完整的签入历史。该二等分会将研究人员指向引起问题的单个原始签入位置。

在给定的代码体中,来自给定的开发人员的注释越多,有关该开发人员的思考过程的文档越简洁。为了继续讨论两分对立的例子,在给出签入注释的情况下,尝试解决原始开发人员在给定更改中的想法的开发人员将获得更大的成功,该注释说明了“ #bisect”造成的十分之一的签入。 ;命令试图完成,而不是他们是否必须从第11个签入注释中解决,这仅说明了“清洁”。折叠功能的版本。

在一个分支中使用一项新功能时,您可能会遇到一个错误,您需要修复该错误才能使该功能继续进行。您可以选择短暂地切换回父分支,在此处开发修复程序,将其签入,然后将父项合并到功能分支以继续工作,但这会分散您的注意力。如果该修复程序不是针对关键错误的,则可以等待在父分支上进行修复,因此最好通过在功能分支上修复该问题来维护您的心理工作状态,然后在功能分支,恢复对功能的工作,然后在以后合并到功能的父分支中。

但是现在,如果另一个分支也需要该修复程序会发生什么呢?让我们说我们的代码存储库有一个用于当前稳定版本的分支,一个用于下一个主要版本的开发分支,以及从开发分支离开的功能分支。如果我们将每个功能分支作为单个签入重新部署到开发分支,仅将重新签入推送到父仓库,则只有该修补程序的开发人员才能在本地获取信息以对修补程序进行精挑细选。稳定分支。

使用新功能的开发人员通常并不关心旧的稳定版本,但是该稳定版本可能具有依赖于该版本的最终用户社区,他们要么不能等待下一个稳定版本,要么希望推迟升级一段时间。这样的用户想要反向移植错误修复,但是创建这些修复的开发人员缺乏提供这些反向移植的动力。因此,存在维护和支持组织,这些组织最终从事此类工作。(有一家著名的公司在这种工作上建立了数十亿美元的企业。)

当每个樱桃签从一个分支完全干净地转移到另一个分支时,这项工作会容易得多,而且我们通过从仍保持完整的最小签入中进行工作,增加了达到该状态的可能性。如果支持组织必须手动从功能检入中解开修复程序,则他们很可能在稳定分支中引入新的错误。即使他们设法毫无错误地完成工作,也要花更多的时间来完成这种挑选。

Cherry-pick合并的逆过程是回退合并。如果仅将折叠的私有工作分支的版本推送到parentrepo,则从该父仓库进行工作的那些成员将无法自动退出进入该私有分支的任何单个签入。其他人必须手动解开合并支票中有问题的部分-进入或退出整个功能。

也许在某些情况下,类似rebase的转换实际上是有用的,但是这些情况很少见,当它们出现时,运行一系列的Cherry-pick合并可以获得相同的拓扑结构,并具有以下优点:

在化石中,樱桃采摘合并保留了诚实而清晰的历史记录。 Fossil记得樱桃签来自何处,并在其时间轴中显示了这一点,因此其他开发人员可以了解基于樱桃签的提交是如何组合在一起的。

Git缺乏记住樱桃选择来源的能力作为提交的一部分。 这一事实没有直接承担本文件的论点,但我们可以进行一些观察结果。 首先,Git忘记了历史,而不是重新划算。 其次,如果Git记住了樱桃选择的来源,Git用户可能对避免rebase有一个更好的论据,因为他们有一个没有失去历史的替代方案。 在提交哲学之前,Fossil的测试意味着在提交它之前可以测试樱桃选择。 因为化石在一个提交中允许多个樱桃挑选,所以它记得他们所有人,你可以这样做,以便在逐步的时尚中复杂合并。 Git将樱桃挑选直接送到存储库,因此如果它导致坏的状态,您必须做一些像Git Reset -Hard修复损坏的东西。 rebasing是一种反模式。 这是不诚实的。 它德里贝 ......