【问题标题】:What's the easiest way to commit and push a single file while leaving other modifications alone?提交和推送单个文件的最简单方法是什么,同时保留其他修改?
【发布时间】:2010-09-12 14:54:55
【问题描述】:

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

【问题讨论】:

  • 这是我在 git 中真正看重的一个功能(我一直都在使用它),并且会让我很难切换...
  • 这实际上不是我现在做事的方式,因为我已经了解了很多关于 hg 的知识。现在我将在本地提交更改,更新回以前的版本并在那里进行更改并“hg push --rev”。仅轻推当前分支。然后更新回其他工作并继续。如果我决定不再想要那份工作,我只会“剥掉”它。更容易,您无需担心被拒绝的文件大块,所有内容都被跟踪并在源代码控制中。

标签: version-control mercurial merge push


【解决方案1】:

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

然后您可以hg shelvehg 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

【讨论】:

    【解决方案2】:

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

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

    我在这个答案中详细介绍了使用hg commit --interactivehttps://stackoverflow.com/a/47931672/255961

    【讨论】:

      【解决方案3】:

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

       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 标志来自动提交更改。

      【讨论】:

        【解决方案4】:

        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 的 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
        

        此时,您已在保留其他本地更改的同时推出了迁移。您的其他更改在队列中的补丁中。我的大部分个人开发工作都是使用补丁队列来帮助我更好地构建我的更改。如果您想摆脱补丁队列并恢复正常样式,则必须导出更改并以“正常” 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 工作流程配合得非常好。

        【讨论】:

        • +1 表示解释,但这看起来非常复杂。将它与“git rebase -i”相比较,它根本不需要思考或设置,我仍然看不出 MQ 如何成为解决“整洁补丁集”问题的可行解决方案(对于凡人!)。看来您无论如何都必须真正规划您的工作流程。
        • 我不确定我是否会将模糊命令行的 20 步过程称为“轻而易举”。
        • 呵呵,好电话。我为他的解决方案写了简短而甜蜜的答案。
        【解决方案5】:

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

        hg commit -m "commit message" filename
        

        然后直接推出。

        hg push
        

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

        hg push --rev .
        

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

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

        【讨论】:

        • 这听起来不错。每当我在 Mercurial 附近的任何地方看到一个字母“q”时,我都会开始眼花缭乱。你可能会被 Steve Losh 的“hg nudge”逗乐:hgtip.com/tips/advanced/2009-09-28-nudge-a-gentler-push
        • 使用阶段(在今天的 Mercurial 中)会使这更容易,没有必要用 push 指定 --rev 以避免推送错误的东西。
        【解决方案6】:

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

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

        【讨论】:

          猜你喜欢
          • 2012-12-09
          • 2020-09-05
          • 1970-01-01
          • 2012-07-13
          • 2022-01-18
          • 2011-05-12
          • 2014-07-05
          • 1970-01-01
          • 2014-01-28
          相关资源
          最近更新 更多