如何在 subversion 中追溯分支,或者如何记录合并补丁的恢复
我在项目上所做的部分开发无法部署,而应该在单独的分支中完成。我已经合并了向后的更改(通过乌龟的“恢复此版本的更改”并仔细编辑),撤消了应该在单独分支中进行的工作,并将这个反向补丁提交到主干。我现在想创建一个分支,其中包含上述补丁中撤消的更改。这就是我所做的:
我在撤消修订之前的修订中为新开发创建了一个新分支。
我通过合并 Tortoise SVN 中的一系列修订将撤消修订合并到新分支中。
我打开更改日志,选择“包括合并的修订”,然后“恢复此修订的更改”。这在我的工作副本中恢复了这些更改。现在这就是我想要的分支的样子。我做出了这些改变。此提交在“包括合并修订”下列出了撤消补丁;我认为不应该这样做;这里似乎有问题。关键可能是以颠覆不知道创建它所执行的操作的方式记录此补丁(平方反比,或原始修改的乘积)。
然后,我通过相同的方法将主干中的所有更改合并到新分支中(合并一系列修订)。这第二次包括了原始的撤消补丁,使我的分支与主干相同(现在将其作为包含的合并修订版列出三次)。这不是想要的结果。
<编辑-解决方案>
以下是所需的行为,并且可以正常工作:
首先,我创建了一个包含文件夹标签、主干、分支的空存储库。在主干中,我创建了一个文件 file.txt,其内容为 (rev1):
one
two
three
然后将该文件编辑为
one
two_edit
three
并签入 (rev2)。然后我在日志中选择了 rev2,并选择了从该版本恢复更改并签入(rev3)。该文件现在看起来又像这样:
one
two
three
然后我创建了一个从 rev3 到branches\b1 的 trunk 分支(rev4、was5;此步骤同时执行这两个操作)。在 Branches\b1 中,文件如下所示:
one
two
three
然后,我将 rev2 从 trunk 反向合并到 Branches/b1 中,忽略祖先 (rev5)。分支现在看起来像这样,现在历史记录包含类似的内容纯粹是巧合:
one
two_edit
three
我编辑主干(rev6),如下所示:
one
two
three
four
我合并主干中的所有更改进入分支/b1(rev7)。 Branches/b1 现在正确地看起来像:
one
two_edit
three
four
<编辑>
它应该如何工作
以下是所需的行为,如果按如下方式执行斜体步骤,则可以正常工作:
首先,我创建了一个包含文件夹标签、主干、分支的空存储库。在主干中,我创建了一个文件 file.txt,其内容为 (rev1):
one
two
three
然后将该文件编辑为
one
two_edit
three
并签入 (rev2)。然后我在日志中选择了 rev2,并选择了从该版本恢复更改并签入(rev3)。该文件现在又看起来像这样:
one
two
three
然后我创建了一个从 rev2 到branches\b1 (rev4) 的 trunk 分支。在 Branches\b1 中,文件如下所示:
one
two_edit
three
然后,我将 rev3 从 trunk 合并到 Branches\b1 (rev5),分支现在如下所示:
one
two
three
我编辑分支 3 (rev6),就好像我此时正在分支一样。现在,历史记录包含类似的内容纯属巧合:
one
two_edit
three
我将主干 (rev7) 编辑为如下所示:
one
two
three
four
我将主干中的所有 更改合并到branches/b1 (rev8) 中。 Branches/b1 现在看起来像:
one
two_edit
three
four
它是如何工作的
以下是实际行为;如果执行斜体步骤,它将无法正常工作,由于追溯分支的复杂性,这是必要的。错误出现在最后一步的第二行。
首先,我创建了一个空的存储库,其中包含文件夹标签、主干、分支。在主干中,我创建了一个文件 file.txt,其内容为 (rev1):
one
two
three
然后将该文件编辑为
one
two_edit
three
并签入 (rev2)。然后我在日志中选择了 rev2,并选择了从该版本恢复更改并签入(rev3)。该文件现在又看起来像这样:
one
two
three
然后我创建了一个从 rev2 到branches\b1 (rev4) 的 trunk 分支。在 Branches\b1 中,文件如下所示:
one
two_edit
three
然后,我将 rev3 从 trunk 合并到 Branches\b1 (rev5),分支现在如下所示:
one
two
three
在 Branches\b1 中,我在日志中选择了 rev5,并从中选择了恢复更改修订并签入(rev6)。文件现在又看起来像这样:
one
two_edit
three
我编辑主干 (rev7),如下所示:
one
two
three
four
我将主干的所有更改合并到branches/b1 (rev8) 中。 Branches/b1 现在看起来像:
one
two
three
four
Part of the development I have done on a project can not be deployed, and should have been done in a separate branch. I have merged in the backwards changes (via tortoise's "revert changes from this revision" and careful editing), undoing the work that should have been in a separate branch, and committed this inverse patch to the trunk. I would now like to create a branch that includes the changes that were undone in the aforementioned patch. Here is what I did:
I created a new branch for the new development at the revision prior to the undo revision.
I merged the undo revision into the new branch via merge a range of revisions in tortoise SVN.
I opened the change log, selected "Include merged revisions", and "revert changes from this revision". This reverted these changes in my working copy. It is now what I would like the branch to be like. I committed these changes. This commit lists the undo patch under "include merged revisions"; I do not believe it should do so; there seems to be a problem here. The key is probably to record this patch (the inverse squared, or the product of the original modifications) in such a way that subversion is ignorant of the operation performed to create it.
I then merged all of the changes from trunk into the new branch via the same method (merging a range of revisions). This included the original undo patch a second time, making my branch identical to trunk (listing it now thrice as an included merged revision). This is not the desired result.
<Edit - Solution>
The following is the desired behavior, and works correctly:
First I created an empty repository with folders tags, trunk, branch. In trunk I created a file file.txt with the content (rev1):
one
two
three
Then edit the file to
one
two_edit
three
And checked in (rev2). Then I selected rev2 in the log and picked revert changes from this revision and checked in (rev3). The file now looks like this again:
one
two
three
I then created a branch of trunk from rev3 to branches\b1 (rev4, was5; this step does both). In branches\b1 the file looks like this:
one
two
three
I then reverse merge rev2 from trunk into branches/b1 ignoring ancestry (rev5). The branch now looks like this, and it is now sheer coincidence that the history contains something similar:
one
two_edit
three
I edit the trunk (rev6) to look as follows:
one
two
three
four
I merge all changes from the trunk into branches/b1 (rev7). branches/b1 now correctly looks like:
one
two_edit
three
four
</Edit - Solution>
<Edit>
How it should work
The following is the desired behavior, and works correctly if the italicized step is performed as follows:
First I created an empty repository with folders tags, trunk, branch. In trunk I created a file file.txt with the content (rev1):
one
two
three
Then edit the file to
one
two_edit
three
And checked in (rev2). Then I selected rev2 in the log and picked revert changes from this revision and checked in (rev3). The file now looks like this again:
one
two
three
I then created a branch of trunk from rev2 to branches\b1 (rev4). In branches\b1 the file looks like this:
one
two_edit
three
I then merge rev3 from trunk into branches\b1 (rev5), the branch now looks like this:
one
two
three
I edit branch 3 (rev6) as if I were branching at this point. It is now sheer coincidence that the history contains something similar:
one
two_edit
three
I edit the trunk (rev7) to look as follows:
one
two
three
four
I merge all changes from the trunk into branches/b1 (rev8). branches/b1 now looks like:
one
two_edit
three
four
How it does work
The following is the actual behaviour; it works incorrectly if the italicized step is performed, which is necessary because of the complexity of the retroactive branch. The error is in the second line of the final step.
First I created an empty repository with folders tags, trunk, branch. In trunk I created a file file.txt with the content (rev1):
one
two
three
Then edit the file to
one
two_edit
three
And checked in (rev2). Then I selected rev2 in the log and picked revert changes from this revision and checked in (rev3). The file now looks like this again:
one
two
three
I then created a branch of trunk from rev2 to branches\b1 (rev4). In branches\b1 the file looks like this:
one
two_edit
three
I then merge rev3 from trunk into branches\b1 (rev5), the branch now looks like this:
one
two
three
In branches\b1 I selected rev5 in the log and picked revert changes from this revision and checked in (rev6). The file now looks like this again:
one
two_edit
three
I edit the trunk (rev7) to look as follows:
one
two
three
four
I merge all changes from the trunk into branches/b1 (rev8). branches/b1 now looks like:
one
two
three
four
</Edit>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您描述的问题(以及您的解决方案)非常常见。当然,立即在一个单独的分支中开始开发“不上线”的更改会更明智,但我知道我们生活的世界并不完美,事情会发生变化;)。
幸运的是,借助 SVN 等良好的版本控制系统,您可以随时随地进行任何更改。并且也有多种不同的方法可以做到这一点。
因此,当您已经为自己回答问题时,我可以自由地起草我如何理解您的问题以及我将如何解决它。下面的图表也将用于内部目的,所以如果它不再对您有帮助,也没有什么坏处。
旁注:我不太熟悉乌龟,但我想它比 SVN 命令行更容易进行挑选(在您的情况下是反向挑选)。特别是如果您有许多分散的提交可供选择。我仍然更喜欢使用 CLI 进行合并操作,因为它通常会更清楚我现在在做什么;)
我希望你无冲突合并我的朋友;)
Christoph
The problem you described (and your solution) is pretty common. Of course it would have been smarter to start the development of the "not-to-go-live" changes in a separate branch right away but I know its not a perfect world we live in and things change ;).
Fortunatly with a good version controll system such as SVN you can bring any change from any time to allmost anywhere. And there is multiple different ways to do that too.
So while you answered your question for yourself allready I took the freedom to draft how I understand your problem and how I would have solved it. The chart below will serve for inhouse purpose too so no harm done if it doesnt help you any more.
On a side note: I am not so familar with tortoise but I guess it makes cherrypicking (reverse cherrypicking in your case) easier than the SVN commandline. Especialy if you have many scattered commits to select. I'd still prefer the CLI for merge operations as it often gets so much clearer what the hell I am doing right now ;)
I wish you conflict-free merges my friend ;)
Christoph
我认为您正在谈论尝试阻止合并跟踪(又名合并信息)被记录在分支中。我认为你可以使用 svn diff 或 svn merge --ignore-ancestry 来做到这一点。请阅读有关高级合并的 SVN 红皮书,特别是 < a href="http://svnbook.red-bean.com/en/1.5/svn.branchmerge.advanced.html#svn.branchmerge.nomergedata" rel="nofollow noreferrer">没有合并信息的合并 和 < a href="http://svnbook.red-bean.com/en/1.5/svn.branchmerge.advanced.html#svn.branchmerge.advanced.ancestry" rel="nofollow noreferrer">注意或忽略祖先。
与从 rev2 分支相比,从 rev3 创建主干分支可能更容易,然后使用 svn diff 或
在 rev3 的分支中应用/捕获从 rev1 到 rev2 的更改svn merge --ignore-ancestry
。或者,您可以查看 svn merge --record-only 来伪造合并,以便 阻止将来的合并,即让分支或主干相信您已经合并了撤消更改,因此它不会再次申请。
I think you are talking about trying to block merge tracking, a.k.a. mergeinfo, from being recorded in the branch. I think you can do this using
svn diff
orsvn merge --ignore-ancestry
. Read the SVN Redbook on Advanced Merging, specifically Merges Without Mergeinfo and Noticing or Ignoring Ancestry.Rather than branching from rev2, it might be easier to create a branch off the trunk from rev3, and then apply/capture the changes from rev1 to rev2 in the branch of rev3 using
svn diff
orsvn merge --ignore-ancestry
.Alternatively, you could look at
svn merge --record-only
to fake a merge in order to block a rev from future merges, i.e. convince the branch or trunk that you already merged the undo change so it doesn't get applied again.在 TortoiseSVN 分支对话框中选择“存储库中的特定修订版”,使用 ... 按钮选择您想要在新分支中使用的最后一个修订版。
分支时照常进行。
<编辑>
I tried to reproduce your problem, it is quite hard to follow what is in the trunk and what is in the branch, but this is how I did.
首先,我创建了一个空的存储库,其中包含文件夹
tags
、trunk
、branch
。在trunk
中,我创建了一个文件file.txt
,其内容为 (rev1):然后我编辑该文件
并签入 (rev2)。然后我在日志中选择了 rev2,并选择
恢复此版本的更改
并签入 (rev3)。该文件现在看起来又像这样:然后,我创建了一个从 rev2 到
branches\b1
(rev4) 的trunk
分支。在
branches\b1
中,文件如下所示:然后我在
trunk
中编辑该文件并签入 (rev5)然后我从
trunk
合并> 到branches\b1
仅选择 rev5 并提交 (rev6)。现在branches\b1\file.txt
看起来像这样,所有内容都按照我的预期合并。
在这个过程中,哪里对你来说是“错误”的?
In the TortoiseSVN branch dialog choose "Specific revision in the repository", use the ... button to pick the last revision you want to have in your new branch.
Proceed as usual when branching.
<Edit>
I tried to reproduce your problem, it is quite hard to follow what is in the trunk and what is in the branch, but this is how I did.
First I created an empty repository with folders
tags
,trunk
,branch
. Intrunk
I created a filefile.txt
with the content (rev1):Then I edited the file to
and checked in (rev2). Then I selected rev2 in the log and picked
revert changes from this revision
and checked in (rev3). The file now looks like this again:I then created a branch of
trunk
from rev2 tobranches\b1
(rev4).In
branches\b1
the file looks like this:Then I edit the file like this in
trunk
and check in (rev5)Then I merge from
trunk
tobranches\b1
picking only rev5 and commit (rev6). Nowbranches\b1\file.txt
looks like thisEverything is merged as I expected.
Where in this process does it go "wrong" to you?
</Edit>