提交和推送单个文件同时不进行其他修改的最简单方法是什么?
我对Mercurial来说还比较陌生,我的团队正在尝试将其作为Subversion的替代产品。
如何提交单个文件并将其推送到另一个存储库,同时不提交工作目录中的其他修改(或者至少不推送到另一个存储库)?
对于我们而言,数据库迁移会发生这种情况。我们希望将迁移提交给源代码管理,以便DBA在我们进行代码修改以与数据库迁移一起进行时可以查看和编辑它。变更尚未准备就绪,因此我们不想将所有变更都推出。
在Subversion中,我只是要做:
svn add my_migration.sql # commit only the migration, but not the other files I'm working on svn commit -m "migration notes" my_mygration.sql
并继续在本地工作。
这不适用于Mercury,因为当我将其推送到另一个存储库时,如果有未删除的更改,它希望我将其删除,合并并提交合并到存储库。合并后提交不允许我们忽略文件,因此会强制我们提交本地存储库中的所有内容。
我能想到的最简单的方法是将文件提交到本地存储库,克隆本地存储库,从实际存储库中获取任何新更改,合并并提交合并,然后将我的更改推出。
hg add my_migration.sql hg commit -m "migration notes" my_migration.sql cd .. hg clone project project-clone cd project-clone hg fetch http://hg/project hg push http://hg/project
这行得通,但是感觉就像我缺少了一些简单的东西,用某种方式告诉Mercurial忽略工作目录中已经存在的文件,只需合并并一起发送文件即可。我怀疑Mercurial队列可以做到这一点,但是我还没有完全了解mq。
多亏了下面的乔什·马修斯(Josh Matthews),搁置命令正是我想要的。我没有看到关于谷歌搜索的任何出色的安装说明,因此这是我用来使其工作的组合内容:
通过以下方式获取:
hg clone http://freehg.org/u/tksoh/hgshelve/ hgshelve
项目中(当前)唯一的文件是hgshelve.py文件。
修改〜/ .hgrc以添加扩展名,指向克隆存储库的位置:
[extensions] hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py
然后,我们可以hg shelve
和hg unshelve
暂时存储更改。它使我们可以在"修补程序块"级别工作,以选择要搁置的项目。似乎没有搁置已列出要添加的文件,只有已在仓库中进行了修改的文件。
解决方案
有一个Mercurial扩展,它实现了搁置和取消搁置命令,从而为我们提供了一种交互方式来指定要存储的内容,直到以后再保存:搁置。
如果我们不想依赖扩展,另一种选择是在本地保留上游存储库的克隆,该克隆仅用于这些类型的集成任务。
在示例中,我们可以简单地将更改拉入/合并到集成/上游存储库中,然后将其直接推送到远程服务器。
tl; dr:我的原始解释看起来很复杂,但我希望它能完全解释如何使用补丁队列。这是简短的版本:
$ hg qnew -m "migration notes" -f migration my_migration.sql $ hg qnew -f working-code # make some changes to your code $ hg qrefresh # update the patch with the changes you just made $ hg qfinish -a # turn all the applied patches into normal hg commits
Mercurial队列使这种事情变得轻而易举,并且使变更集的更复杂的操作成为可能。值得学习。
在这种情况下,我们可能需要先保存当前目录中的内容,然后再进行更改:
# create a patch called migration containing your migration $ hg qnew -m "migration notes" -f migration.patch my_migration.sql $ hg qseries -v # the current state of the patch queue, A means applied 0 A migration.patch $ hg qnew -f working-code.patch # put the rest of the code in a patch $ hg qseries -v 0 A migration.patch 1 A working-code.patch
现在,让我们在工作代码上做一些额外的工作。为了明确起见,我将继续执行" qseries",但是一旦建立了补丁队列的心理模型,我们就不必继续查看列表了。
$ hg qtop # show the patch we're currently editing working-code.patch $ ...hack, hack, hack... $ hg diff # show the changes that have not been incorporated into the patch blah, blah $ hg qrefresh # update the patch with the changes you just made $ hg qdiff # show the top patch's diff
由于所有工作现在都保存在补丁队列中,因此我们可以取消应用这些更改,并在获取远程更改后将其还原。通常要取消应用所有补丁,只需执行hg qpop -a即可。只是为了显示对补丁队列的影响,我一次将它们弹出。
$ hg qpop # unapply the top patch, U means unapplied $ hg qseries -v 0 A migration.patch 1 U working-code.patch $ hg qtop migration.patch $ hg qpop $ hg qseries -v 0 U migration.patch 1 U working-code.patch
至此,目录似乎没有任何更改。执行" hg fetch"。现在,我们可以重新推送补丁队列更改,并在存在任何冲突时将其合并。从概念上讲,这有点类似于git的rebase。
$ hg qpush # put the first patch back on $ hg qseries -v 0 A migration.patch 1 U working-code.patch $ hg qfinish -a # turn all the applied patches into normal hg commits $ hg qseries -v 0 U working-code.patch $ hg out migration.patch commit info... blah, blah $ hg push # push out your changes
此时,我们已在保留其他本地更改的同时推出了迁移。其他更改位于队列中的补丁程序中。我的大部分个人开发工作都是使用补丁队列来帮助我更好地组织更改。如果要摆脱修补程序队列并返回到常规样式,则必须导出更改,然后以"常规"方式重新导入它们。
$ hg qpush $ hg qseries -v 0 A working-code.patch $ hg export qtip > temp.diff $ rm -r .hg/patches # get rid of mq from the repository entirely $ hg import --no-commit temp.diff # apply the changes to the working directory $ rm temp.diff
我沉迷于补丁队列以进行开发,mq
是那里最好的实现之一。同时进行多项更改的能力确实可以提高重点和清理提交的方式。要花一些时间才能习惯,但是在DVCS工作流程中它进展得非常好。
从我最初提出这个问题到现在已经快两年了。我现在将以不同的方式进行操作(正如我在上述问题上方的评论中提到的那样)。现在,我要做的是将更改提交到本地存储库中的一个文件中(我们可以使用hg记录扩展名仅提交文件的一部分):
hg commit -m "commit message" filename
然后将其推出。
hg push
如果由于首先需要对存储库进行了其他更改而导致发生冲突,那么我将更新到父修订版(如果我们不知道它是什么,请使用" hg parent -r"查看)我在那里其他的变化,所以我有2个头。然后恢复到原始的单个文件提交,并将更改拉入/合并到该版本中。然后使用
hg push --rev .
仅推出单个文件和该修订版的合并。然后,我们可以合并在本地拥有的两个主管。
这种方式消除了mq的东西和被拒绝的大块头的可能性,并通过源代码控制来跟踪所有内容。如果我们以后决定不想使用它们,也可以关闭" hg strip"修订版。