Mercurial 合并提交
2009 年 7 月 9 日
我最近用 Mercurial 合并了一些提交,所以想写一篇博文,以防其他人也想要这样做。我不知道这是否是最好的方法,但对我来说似乎效果很好。
hg clone base working # tip of base is revision 73 cd working # do work, committing on the way cd .. hg clone working squash cd squash hg qimport -r 74:tip hg qgoto 74.diff hg qfold $(hg qunapp) hg qfinish -a cd ../base hg pull ../squash
我做的基本任务是将一些文件和文件夹进行相当严重的移动。我想分几个步骤来完成这项工作,以便在过程中对我的工作进行检查点,但我想要在版本历史中进行一次提交。(我了解到 git 可以通过 rebase 更轻松地做到这一点。)进行一次提交可以更容易地理解发生了什么 - 特别是由于移动文件往往会使查看存储库日志变得复杂。移动文件也会使流程变得复杂 - 有几次我最终得到一个无法正常工作的流程,因为它失去了跟踪移动的能力 - 我希望能够执行 hg log -f
并查看在移动之前原始提交的时间和内容。
首先,我需要启用 mq 扩展(Mercurial 队列)并将我的差异设置为 git 风格。Git 风格的差异有助于正确跟踪文件移动。
# in ~/.hgrc [extensions] mq= [diff] git=true
以这种方式使用 Mercurial 时,似乎一般的工作方式是拥有多个存储库。Mercurial 鼓励使用不同的存储库,而其他系统(例如 git 或 svn)会使用不同的分支。人们对此争论不休,但这是 Mercurial 的工作方式。在这个例子中,我将“base”作为我的原始存储库。
我的第一步是将 base 克隆到一个工作存储库中。
hg clone base working
此时,base(和 working)的顶端是修订版 73。我进行了文件移动,并在过程中进行了几个检查点修订。
cd working hg mv foo1 newdir/foo1 .. more hg mv .. hg ci -m "moving around" .. more hg mv .. hg ci -m "moving around" .. more hg mv and hg ci.. cd ..
当我完成时,最后一个修订版是 80。
为了将它们压缩成一个提交,我克隆了另一个存储库。
hg clone working squash
此时克隆很重要,因为我将要编辑历史记录,所以我想保留原始历史记录,直到我知道它已经成功。我现在进入那里。
cd squash
现在,我将为修订版完成的所有提交都变成了 Mercurial 修补程序队列机制的修补程序。
hg qimport -r 74:tip
我将第一个更改设置为当前修补程序
hg qgoto 74.diff
我将所有修补程序压缩成一个修补程序
hg qfold $(hg qunapp)
这个折叠修补程序的提交消息将是所有单独的提交消息链接在一起。我想要一个单独的消息来表示我的干净提交。
hg qrefresh -m "reorganized files"
然后,我将修补程序变成了一个常规的提交。
hg qfinish -a
我现在有一个包含所有工作的单个提交。我查看了它,以确保一切正常,特别是测试了 hg log -f
对一些移动的文件,以确保历史记录仍然存在。一旦我确信一切正常,我就将单个变更集拉入 base 存储库。
cd ../base hg pull ../squash
有趣的是,看看多年来人们对版本控制系统的关注是如何变化的。早期,主要且唯一的目的是审计 - 能够安全地回到旧的修订版 - 主要用于诊断问题。然后,人们的注意力转移到它们如何使人们之间的协作成为可能。这并没有取代对审计的需求,而是在其基础上进行了构建。现在,人们更加关注使用它们来提供代码库如何变化的叙述 - 因此人们渴望使用像这样的历史重写命令。同样,这种需求是在其他两种需求的基础上构建的,但它引入了新的功能和新的紧张局势。
感谢我的同事 Chris Turner 的帮助,我还发现 这个页面 非常有用。