【发布时间】:2013-12-30 17:12:49
【问题描述】:
在重构源代码时,有时您需要将大块文本移动到文件中,甚至移动到新文件中。你创建一个分支refactored 并提交:
$git checkout master
$git branch refactored
$git checkout refactored
<move code around>
$git commit -m "refactored code"
但是,人们可能会在旧的预重构分支之上提交,从而更改已移动的代码:
$git checkout master
<change code that was moved elsewhere on branch refactored>
$git commit -m "bugfix"
在分支 refactored 上,您想要合并在 master 中所做的更改:
$git checkout refactored
$git merge master
<giant merge conflict>
这会导致大的合并冲突。如果有办法告诉 git 内容只是简单地移动了,那么应该可以自动合并。
更糟糕的是,即使在解决冲突并提交之后,git 仍然无法使用该解决方案来确定进一步的合并:
<fix conflicts>
$git commit -m "merge master into refactored"
$git checkout master
<change more code>
$git commit -m "bugfix2"
$git checkout refactored
$git merge master
<another giant merge conflict>
这完全可以避免吗?我试过git rerere 并不能解决这里的冲突。 git有什么办法可以将文本块移动为实际移动,而不是删除和插入?如果不能,如果您需要将两个并行分支保留一段时间,那么最大限度地减少合并冲突的最佳方法是什么?
虽然这对moving the contents of a complete file 来说很容易,但我找不到关于仅移动它的部分或在同一个文件中移动的信息。
另外,如果有解决方案,git blame 在重构时的行为会是什么?
代码?它会指向重构提交,还是忽略它?有没有办法实现后者?
如果有人感兴趣,我已将我用于测试的(非常小的)存储库的 base64 编码 tar.gz 放入on pastebin
可能的解决方案
一个潜在的解决方案可能是通过在预重构分支中应用(自动)编辑的补丁来执行合并。有没有为此开发的软件?使用这种方法我猜想,因为这对 git 是透明的,git blame 将指向重构提交。
我找到了the same question, applied to diff。没有提到任何现有的非专有实现,但提到了跟踪块移动的算法
【问题讨论】:
-
我建议你做出更多的承诺。当您更改大量数据时,您有更多的提交,合并代码时遇到的问题更少。
-
@sensorario 总的来说这是一个很好的建议。不过,我不确定您如何将其应用于重构 - 一次移动一个函数/小块不会有帮助
-
如果您更改文件,您有两个不同的内容。是的,如果你将一个函数从一个文件移动到另一个文件。如果您想尽量减少冲突,请进行越来越多的提交。请尝试。
-
@sensorario 我已经尝试将一个块仅移动 3 行,并更改
master中的中间行。还是有冲突 -
在
master之上重新设置refactored怎么样?你还会有合并冲突吗?
标签: git merge diff merge-conflict-resolution