提交和推送单个文件同时不进行其他修改的最简单方法是什么?


72

我对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。


1
这是我真正珍视git的功能(我一直都在使用它),这会让我很难切换...
Jared Forsyth 2010年

12
现在,我对汞有了更多的了解,这实际上并不是我会做的事情。现在,我将在本地提交更改,更新回先前的版本,然后在此处进行更改,然后单击“ hg push --rev”。仅微移当前分支。然后更新回其他工作并继续进行。如果我决定不想再工作了,我就把它“去除”。变得容易得多,而且您不必担心文件被拒绝的麻烦,所有内容都将被跟踪并在源代码控制中。
泰德·纳莱德

Answers:


31

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

那么你也能 hg shelvehg unshelve暂时存储更改。它使您可以在“修补程序块”级别工作,以选择要搁置的项目。似乎没有搁置列出要添加的文件,只有已在仓库中进行了修改的文件。

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


真正旧版本的Mercurial的注释(在包含之前-不再需要):

我没有看到关于谷歌搜索的任何出色的安装说明,因此这是我用来使其工作的组合内容:

通过以下方式获取:

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

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

修改〜/ .hgrc以添加扩展名,指向克隆存储库的位置:

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py

40

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

hg commit -m "commit message" filename

然后将其推出。

hg push

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

hg push --rev .

仅推出单个文件和该修订的合并。然后,您可以合并在本地拥有的两个主管。

这种方法消除了mq的东西和被拒绝的块的可能性,并通过源代码控制来跟踪所有内容。如果您以后决定不想使用它们,也可以关闭“ hg strip”修订版。


1
听起来不错。每当我在Mercurial附近的任何地方看到字母'q'时,我都会开始大吃一惊。您可能会对史蒂夫·洛(Steve Losh)的“汞轻推”感到好笑:hgtip.com/tips/advanced/2009-09-28-nudge-a-gentler-push
汤姆·安德森

使用阶段(在今天的Mercurial中)将使此过程变得更加容易,无需--rev为了避免推送错误而指定 push。
UuDdLrLrSs

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

在这种情况下,您可能需要先保存当前目录中的内容,然后再进行更改:

# 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工作流程中进展得非常好。


+1作为解释,但这看起来非常复杂。将其与“ git rebase -i”进行比较,后者根本无需考虑或设置,我仍然看不到MQ如何解决“整洁的补丁集”问题(对于凡人!)。看来您还是必须真正计划工作流程。
richq

20
我不确定我会将20步的晦涩难懂的命令行流程称为“轻轻松松”。
Crashworks,2009年

1
呵呵,打个好电话。我为他的解决方案写了简短而可爱的答案。
Kobold

3

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

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


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标志。


1

因为您说的最简单,所以hg commit -i即使提交整个文件,我也经常使用(--interactive)。有了它们,--interactive您只需选择所需的文件,而不用在命令行中输入其完整路径。作为额外的好处,您甚至可以在文件中选择性地包括/排除块。

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.