尽管我已经尽力避免它,但我必须维护三个master
等价的分支,每个分支都有微小的更改。我一直在阅读有关git
的文章,并使用了几年,所以我熟悉以下传统观点:
1.除非有意义,否则不要使用merge
。使用rebase
。
1.如果你只需要拉入一个提交,cherry-pick
是你的朋友。
1.在按下之前,始终在遥控器上按pull --rebase
。
1.保持功能与rebase
一致。
他们没有告诉你的是,传统智慧会创建一堆几乎相同的提交,除了一些改变SHA1的小细节。为什么这很重要?它违背了用git log --left-right --graph --cherry-pick --oneline branch1..branch2
和git show-branch
比较分支的目的,这尤其令人讨厌。感觉像是对廉价分支的滥用。这使得几乎不可能看到每个分支缺少哪些补丁。
那么,如何使多个分支与相同的SHA1保持一致,以便可以使用这些工具?补丁是最好的方法吗?
3条答案
按热度按时间bxjv4tth1#
您不能在多个位置保存具有相同SHA的提交,因为提交的“位置”(其在历史中的位置)由SHA标识。
Git提交包含某些数据,其中包括当前repo状态的快照,当前时间和日期,提交者名称和电子邮件,以及父提交的SHA。
这意味着当你把一个提交放到其他地方(
rebase
,cherry-pick
,patch+apply)或者改变它的时间(commit --amend
),* SHA值会不同。*这是Git的一个重要特性(Git历史记录是所谓的Merkle tree)。
正如你所注意到的,你可以通过使用我上面提到的各种历史重写命令来维护 *(内容)等价的 * 提交。
根据你的情况,你 * 可能 * 可以使用
master
中的提交,而不必复制它们。如果那些使你的“master
-equivalent”分支不同的更改是纯添加性的(即它们发生在提交中,这些提交总是可以 * 追加 * 到master中的最新提交),那么你就可以总是把你的其他分支重新基到master
上,并且很高兴,因为这样它们就简单地包含了master
的所有提交。另一方面,如果您的更改属于需要在历史记录中更早插入的类型(即新提交到
master
* 必须 * 追加 * 后 * 你的差异化变化),那么你将无法保持一个“漂亮”的历史。我不能自发地想到第二种情况的例子,但它在理论上是可能的(无论是内容实际需要,还是项目规范等外部因素需要)。
wdebmtf22#
我不认为这是传统智慧不合并,除非它是有意义的。如果你想让历史记录保持相同的SHA1哈希值,请合并,并避免挑选。
byqmnocz3#
我认为这个问题的某些前提是错误的。
Git使用内容寻址数据库,因为(除其他外)它希望保护版本历史的完整性。每一小块提交元数据都计入SHA1,因此它每次都会改变。
另一方面Git是分布式的,允许您使用分布式工作流。比如通过电子邮件发送补丁。[1]补丁不是提交(快照)。所以你最终得到了一个两级系统:
1.发表历史
1.动态变化(电子邮件补丁,你已经维护了两年的补丁堆栈,因为上游还没有接受它,……)
你们应当这样做:
git cherry
和其他命令来比较使用 patch id 的提交(基本上是一个diff标准化;比较提交引入的更改)因此,这是两种处理历史的方法(分别是稳定的和动态的)-使用合并等。并且总的来说,将变化视为不可变的对于稳定的、已发布的历史来说更符合人体工程学。另一方面,将更改视为“补丁”对于某些工作流中的动态历史记录来说是非常必要的。但是,在我看来,在稳定的历史记录上使用飞行中的历史记录工具只会让你的生活变得更加困难,而且好处很少。您可能会保存执行一些额外的合并,但最终您可以在历史中接受这些合并。
注意事项
1.我们也可以进入rebase工作流,但是选择一个需要使用
git cherry
之类的东西的例子更容易,因为你不能在补丁电子邮件上执行git merge