72

我对 Mercurial 比较陌生,我的团队现在正在尝试将它作为 Subversion 的替代品。

我如何提交单个文件并将其推送到另一个存储库,同时保留我的工作目录中的其他修改未提交(或至少不推送到另一个存储库)?

这发生在我们的数据库迁移中。我们希望将迁移提交到源代码控制,以便 DBA 可以在我们进行代码修改以进行数据库迁移时查看和编辑它。更改尚未准备好进行,因此我们不想将所有更改都推出。

在颠覆中,我会简单地做:

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

并继续在本地工作。

这不适用于 mercurial,因为当我将其推送到另一个存储库时,如果我没有拉下它的更改,它希望我将它们拉下,合并它们,并将合并提交到存储库。合并后的提交不允许您省略文件,因此它会强制您提交本地存储库中的所有内容。

我能想到的最简单的事情是将文件提交到我的本地存储库,克隆我的本地存储库,从实际存储库中获取任何新更改,合并它们并提交该合并,然后它们将我的更改推送出去。

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。

4

6 回答 6

40

自从我最初提出这个问题以来已经快 2 年了。我现在会采取不同的做法(正如我在上述问题上方的评论中提到的那样)。我现在要做的是将我的更改提交到本地存储库中的一个文件(您可以使用 hg 记录扩展名仅提交文件的一部分):

hg commit -m "commit message" filename

然后直接推出。

hg push

如果由于对我需要首先合并的 repo 进行了其他更改而发生冲突,我将更新到父版本(使用“hg parents -r”查看。如果你不知道它是什么),提交我在那里的其他变化,所以我有2个头。然后恢复到原始的单个文件提交并将更改拉/合并到该版本中。然后推出更改

hg push --rev .

仅推出单个文件并合并该修订。然后你可以合并你在本地得到的两个头。

这种方式摆脱了 mq 的东西和被拒绝的大块的可能性,并通过源代码控制跟踪所有内容。如果您以后决定不想要它们,您也可以“删除”修订。

于 2010-07-13T17:33:39.953 回答
31

Mercurial 有一个实现搁置和取消搁置命令的功能,它为您提供了一种交互式方式来指定要存储到以后的更改:搁置

然后,您可以hg shelve临时hg unshelve存储更改。它使您可以在“补丁大块”级别工作,以挑选要搁置的项目。它似乎没有搁置列出的要添加的文件,只有已经在 repo 中有修改的文件。

它作为“扩展”包含在 Mercurial 中,这意味着您必须在 hg 配置文件中启用它。


真正旧版本的 Mercurial 的注意事项(在 shelve 包含之前 - 这不再需要):

我没有通过谷歌搜索看到任何很好的安装说明,所以这是我用来让它工作的组合内容:

得到它:

hg clone http://freehg.org/u/tksoh/hgshelve/ hgshelve

项目中唯一的文件(当前)是 hgshelve.py 文件。

修改你的 ~/.hgrc 以添加搁置扩展,指向你克隆 repo 的位置:

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py
于 2008-09-24T03:41:32.393 回答
10

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 Queues 使这种事情变得轻而易举,它使更复杂的变更集操作成为可能。值得学习。

在这种情况下,首先您可能希望在下拉更改之前保存当前目录中的内容:

# 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 的变基。

$ 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

此时,您已在保留其他本地更改的同时推出了迁移。您的其他更改在队列中的补丁中。我的大部分个人开发工作都是使用补丁队列来帮助我更好地构建我的更改。如果您想摆脱补丁队列并恢复正常样式,则必须导出更改并以“正常” mercurial 重新导入它们。

$ 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 工作流程配合得非常好。

于 2009-02-20T12:39:22.010 回答
3

如果您不想依赖扩展,另一种选择是在本地保留上游存储库的克隆,仅用于这些类型的集成任务。

在您的示例中,您可以简单地将更改拉入/合并到集成/上游存储库中,并将其直接推送到远程服务器。

于 2008-10-10T01:35:31.860 回答
2

我通常使用的是用于提交单个文件:

 hg commit -m "commit message" filename

万一以后,我有一个合并冲突,我还没有准备好提交我的更改,请按照以下步骤操作:

1) 创建补丁文件。

hg diff > changes.patch

2) 仅在检查补丁文件后恢复所有未提交的更改。

hg revert --all

3) 拉取、更新和合并到最新版本

hg pull -u
hg merge
hg commit -m "local merge"

4) 现在只需导入您的补丁并获取您的更改。

hg import --no-commit changes.patch

请记住在自动提交更改时使用 -no-commit 标志。

于 2015-02-03T22:00:14.390 回答
1

既然你说最简单,hg commit -i即使提交整个文件,我也经常使用 (--interactive) 。您只需--interactive选择您想要的文件,而不是在命令行上输入它们的整个路径。作为额外的奖励,您甚至可以有选择地在文件中包含/排除块。

然后只是hg push推送新创建的提交。

hg commit --interactive在此答案中提供了有关使用的更多详细信息:https ://stackoverflow.com/a/47931672/255961

于 2017-12-21T19:42:18.410 回答