【问题标题】:Mercurial Patch Creation and UsageMercurial 补丁创建和使用
【发布时间】:2010-12-27 12:37:13
【问题描述】:

我遇到了一个我“认为”只能通过补丁解决的问题。

我从我们的主存储库克隆了一个项目,对其进行了很多更改(更新、删除文件和目录以及添加)。这些更改甚至没有提交。问题是,主存储库中的项目已被删除/删除并重新创建为新项目(名称相同,所有目录结构都与以前相同)。我再次从主存储库克隆了该项目,并希望将所有未提交的更改转移到它。

我仍在探索hg patch 来解决这个问题。如果有人能够确认创建和添加补丁是解决此问题的正确方法,那将很有帮助,任何解释该过程的资源都会有很大帮助。

【问题讨论】:

  • 为什么要重新创建 repo?这样做会使所有克隆无效,请确保您的团队中没有人认为这样做是安全的操作,因此这种操作会定期发生。

标签: mercurial patch


【解决方案1】:

您说得对——补丁是将信息从一个存储库传输到另一个(不相关的)存储库所需的。正如您所注意到的,这将起作用,因为文件是相同的。

因此,要从您的 old 克隆转移您未提交的更改,您可以这样做

$ hg diff -g > uncommited.patch
$ cd ../new
$ hg patch --no-commit ../old/uncomitted.patch

这将恢复保存在补丁中的信息。这包括有关在旧克隆中添加或重命名的文件的信息。

【讨论】:

    【解决方案2】:

    可以使用标准 Mercurial 安装执行以下步骤:

    1. 在本地存储库中提交更改。记下修订号。
    2. 使用“hg export -r REV >patch.diff”创建补丁。
    3. 克隆新的存储库。
    4. 使用“hg import patch.diff”将补丁应用到新的存储库。

    示例

    C:\>hg init example
    C:\>cd example
    C:\example>echo >file1
    C:\example>hg ci -Am file1
    adding file1
    
    C:\example>hg clone . ..\example2
    updating to branch default
    1 files updated, 0 files merged, 0 files removed, 0 files unresolved
    
    C:\example>rd /s/q .hg
    C:\example>hg init
    C:\example>hg ci -Am same-but-different
    adding file1
    

    此时exampleexample2 内容相同,但由于删除并重新初始化.hg 文件夹,存储库彼此无关。

    现在进行一些更改并将它们提交到其中一个存储库中,然后将它们导出为补丁:

    C:\example>echo >>file1
    C:\example>echo >file2
    C:\example>hg ci -Am changes
    adding file2
    
    C:\example>hg export -r 1 >patch.diff
    

    下面显示由于重新初始化,其他存储库无法提取更改。但是,它可以成功应用补丁:

    C:\example>cd ..\example2
    C:\example2>hg pull
    pulling from c:\example
    searching for changes
    abort: repository is unrelated
    
    C:\example2>hg import ..\example\patch.diff
    applying ..\example\patch.diff
    

    【讨论】:

      【解决方案3】:

      我会先复制所有内容,这样你就有办法回溯。

      然后,在包含更改的工作副本中,我将首先删除 .hg 目录,然后从新的 repo 中复制到 .hg 目录中。这基本上将所有更改的文件转移到新的 repo 中,而无需删除任何文件和目录。

      您仍然需要告诉 repo 是否删除任何标记为丢失的文件。您还必须手动处理重命名。如果这是少量操作,那比尝试使用patch方法更容易。

      完成此操作后,提交您的更改并在必要时推送。

      【讨论】:

      • 嗯,听起来很有趣,我只是想知道为什么我必须手动处理重命名,是因为新的 .hg 目录不知道更改吗?如果是这种情况,那么新的 .hg 将不会对任何文件有任何了解?每当我重命名文件时,都会显示 Mercurial 状态!和 ?针对新旧文件,这是预期的。
      • 重命名文件时应使用“hg rename”,以便在文件重命名时跟踪历史记录。
      • 因为重命名必须通过 hg 中的显式命令来完成以维护文件历史记录,我们通过在文件系统级别有效地重命名任何更改的文件名来规避这一点。 TortoiseHg 有一个 Guess Renames 函数可以自动执行此操作,但如果只是几个文件,您不妨将它们命名为旧名称,然后使用 hg 的 rename 函数恢复为新名称。跨度>
      • 猜测从命令行重命名为hg addremove --similarity 90
      • 很抱歉,不应该删除 .hg 目录 — 这样做也会删除“dirstate”,这是 hg rename a bhg add c 之类的东西在它们之前被跟踪的地方已提交。
      【解决方案4】:

      似乎你想要的是补丁队列。因为您有未提交的更改,并且您希望在提交之前从新的仓库中提取......

      $ hg qinit -c # initialize mq for your repo containing the uncommitted changes 
      $ hg qnew name_of_patch # create patch that contains your uncommitted changes
      $ hg qpop # resets your working dir back to the parent changeset
      

      不过不用担心,您的更改在 .hg/patches/name_of_patch 中是安全可靠的,您可以自己查看.....

      $ cat .hg/patches/name_of_patch
      

      现在拉入新的仓库

      $ hg pull -u http://location.of.new/repo # pull in changes from new repo update working dir
      
      $ hg qpush # apply your uncommitted changes to new repo
      

      如果你很幸运,你不会有合并冲突,你可以继续提交补丁......

      $ hg qfinish -a # change all applied patches to changeset
      

      如果你愿意的话……

      $ hg push http://location.of.new/repo
      

      如果 repos 不相关,只需在新 repo 上初始化一个补丁 repo。并手动复制补丁并将其添加到 .hg/patches/series 文件中。

      假设补丁已创建。克隆新的仓库

      $ hg clone http://location.of.new/repo ./new_repo
      

      初始化补丁仓库

      $ cd ./new_repo && hg qinit -c
      

      复制补丁

      $ cp ../old_repo/.hg/patches/name_of_patch .hg/patches/
      

      使用某种编辑器编辑系列文件

      $ your_favorite_editor .hg/patches/series
      
      name_of_patch   # <---put this in the series file
      

      将你的补丁应用到新的仓库

      $ hg qpush
      

      如果没有合并冲突并且您确信它有效

      $ hg qfinish -a
      

      【讨论】:

        【解决方案5】:

        如果布局相同,您可以将所有文件复制过来(不包括.hg),然后使用hg addrem

        【讨论】:

        • 我认为这是一个手动且不完整的解决方案,首先我确保复制所有文件,然后从新文件中删除文件和目录。
        【解决方案6】:

        尝试查看 MQ 插件,如果我记得的话,它就是这样做的。不过我从来没有用过,所以我不能说。

        【讨论】:

          【解决方案7】:

          如果旧存储库只是简单地移动/克隆到新 URL,那么您可以简单地更改与新存储库通信的远程存储库。

          但是,如果它是从头开始重新创建的(即使具有相同的结构),那么我认为 Mercurial 没有任何内置功能可以帮助您。 Mercurial 补丁引用了新存储库中不存在的特定变更集。

          您可以使用合并工具来执行差异并带来您所做的任何更改。

          编辑回答评论中的问题: 当您克隆存储库时,您正在获取整个更改历史记录的完整快照 - 以及关联的更改集 ID 等。

          Mercurial 通过对存储库的更改集来跟踪更改,而不是像 Subversion 那样在文件级别跟踪更改。

          如果您克隆,那么您可以轻松地推送/合并到另一个同样从同一来源克隆的存储库。

          如果您重新创建了存储库,那么更改 ID 将不匹配,并且无法在 Hg 中合并。 在这种情况下,唯一的选择是使用合并工具,它可以让您查看文件/文件夹结构中的不匹配。

          另外:值得指出http://hginit.com/,因为它(间接)解释了其中的一些。

          【讨论】:

          • 嘿,Will,URL 完全相同,但项目被删除然后重新创建。移动/克隆和从头开始重新创建的区别是什么?
          • 嘿,添加了我对答案的回复(有点太长,无法放入评论)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-08
          • 1970-01-01
          • 1970-01-01
          • 2012-04-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多