重写 Git 历史的实际后果是啥?

Posted

技术标签:

【中文标题】重写 Git 历史的实际后果是啥?【英文标题】:What are the practical consequences of rewriting Git history?重写 Git 历史的实际后果是什么? 【发布时间】:2010-12-02 05:41:53 【问题描述】:

我们的项目已经使用 Git 大约一周了,我们都非常喜欢它(在紧密协作的团队中使用它,结果证明是完全不同的 Git 体验)。为了使事情尽可能简单,我们不做任何变基或历史修改。但是我们在第一周确实犯了一些错误。进行了一些不应该进行的提交,我们设法将功能分支合并到错误的集成分支中(1.1 而不是 1.0)。直到它们进入我们的历史很长一段时间后,我们才发现这些东西。

现在我看到很多关于重写历史的警告,但我不确定我是否了解其中的危险。我们使用共享的裸仓库,所有分支都推送到那里进行备份。

我希望如果您重写历史记录(例如删除提交),后续提交的完整列表将“丢失”该提交(并且可能无法编译/工作)。我还希望如果发生这种情况,我实际上可以选择在历史记录的顶部修复这个问题(并将历史记录的那部分保留为非编译)。

如果我重写历史记录(并且所有内容都在所有受影响的分支中编译/工作),我的同事是否需要执行任何特殊命令? (换句话说,如果我做得好,他们会“知道我做到了”吗?) 是否有我不知道的本地更改的任何用户有资格在 git pull 上合并失败? 我在这里遗漏了什么重要的东西吗?

任何对这个主题的文章/教程的引用也非常好。

【问题讨论】:

@Goober:我在这里的天真回应,有问题吗?我们是测试驱动的,所以我相信我们会抓住它 【参考方案1】:

需要阅读 Git 用户手册中的Problems with rewriting history。

如果我重写历史记录(并且所有内容都在所有受影响的分支中编译/工作),我的同事是否需要执行任何特殊命令(即,如果我做得好,他们会“知道我已经完成了它”吗?)?

他们会知道,Git 会毫不含糊地告诉他们某事是错误的。他们将收到意外的错误消息,并且可能在尝试解决由此产生的合并冲突的过程中,无意中恢复以前的提交。这个问题会产生一个真实的消息,如果您想知道会发生什么,您可以随时在您的存储库的临时副本上尝试它。

是否有任何我不知道的本地更改的用户有资格在 git pull 上合并失败?

当然,见上文。

我在这里遗漏了什么重要的东西吗?

(几乎)不惜一切代价避免重写历史记录!

【讨论】:

我实际上已经阅读了手册的那部分,感觉就像我已经阅读了所有手册 RSN ;) 重写的分支是否总是获得新的身份?这确实解释了为什么永远不应该这样做...... 由于 Git 通过其内容识别提交的方式和所有以前的提交,对提交的任何更改(无论多么微小)都将看起来像是 Git 开发的全新分支.没有办法让重写的历史看起来“几乎一样”。 谢谢,奇怪的是,在 git 中遗漏一小部分信息会带来很大的不同。 这被广泛认为是 Git 存储库格式的一个功能。如果那一小部分信息非常重要怎么办?请参阅:keithp.com/blogs/Repository_Formats_Matter,了解有关该主题的精彩帖子。 对不起,我不是很清楚:我不明白重写 histroy 必须 来创建一个派生分支。现在我知道我不再有任何关于重写历史的悬而未决的问题;)我明白我完全在重写之后创建的任何特性分支上拉扯地毯。【参考方案2】:

正如在其他答案 cmets 中提到的,实际上每个提交都是唯一的,重写历史记录将进行新的提交。

你可以把它想象成砍掉树枝,然后立即长出新的树枝。它们甚至可能看起来相同,但实际上并非如此。是的,巫毒魔法。在这个类比中,还原几乎就像用一根原木支撑一根掉落的树枝,所以它会按照自己的方式生长而不会掉落。

这将我们引向a couple good reasons to rewrite history:

在公开之前精简私有存储库:例如,创建一个新的本地私有分支、测试、测试、重写、推送。 在公开之前从私有存储库中删除敏感数据。

那些已经揭示了 Greg 已经说过的内容:如果存储库是公共的(推送提交),则重写历史记录 will potentially screw up everyone。为什么我也主张不惜一切代价避免在私人回购中这样做的原因,只是为了保持好习惯:所以应该不惜一切代价避免重写历史 (这意味着只是给在做之前有足够的考虑:权衡利弊!)

至少还有另一个被忽视的哲学原因:重写历史就是丢失数据。诚然,revert 的 git 历史可能看起来比 reset 更混乱。但是,如果编写得当,所有这些“混乱”都可以隐藏在单独的分支中,我们仍然可以准确地看到在什么时候完成了还原。甚至有理由或证据说明为什么这样做。

回到树的类比,即使去掉支撑的原木,恢复的树枝也会呈现出蜿蜒的生长曲线,很漂亮!

【讨论】:

请注意,“重写历史”一章有一个更新的(第 2 版)。 git-scm.com/book/en/v2/Git-Tools-Rewriting-History 我同意告诉人们在做某事是个好主意时要像成年人一样学习和判断。重写历史,经常在其他人(尚未)工作的功能分支上完成,这是我们公司必须和强制性的。 @XavierAriasBotargues 也许这确实是重写的最引人注目的日常使用:在实践中,在进行单独开发时,清理东西并删除许多无用的混乱要容易得多。无论如何,为了保持这段历史而付出额外的努力几乎没有收获。仍然...我希望您的公司不会关闭那些将恢复的公司。 ;P

以上是关于重写 Git 历史的实际后果是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Git 重写历史

Git 重写历史

如何重写 git 历史以匹配流行的 git 工作流程

是否可以在不重写历史记录的情况下精简 .git 存储库?

关于 Git 重写历史的一些笔记

Git之深入解析如何重写提交历史