在重构源代码时,有时需要将大块文本移动到文件中的其他位置,甚至移到新文件中。创建一个名为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将文本块的移动视为实际的移动,而不是删除和插入?如果不能,那么在需要保留两个平行分支一段时间的情况下,最好的方法是什么,以最小化合并冲突?
虽然这对于移动完整文件的内容很容易,但我找不到有关移动其中部分或在同一文件中移动的信息。
此外,如果有解决方案,重构代码时git blame
的行为会是什么?它会指向重构提交,还是忽略它?有办法实现后者吗?
如果有人感兴趣,我在pastebin上放了一个(非常简单的)测试库的base64编码tar.gz
可能的解决方案
一个潜在的解决方案可能是通过应用包含来自预重构分支中更改的(自动编辑的)补丁来执行合并。有开发的软件可以做到这一点吗?使用这种方法,我猜由于这对git是透明的,git blame
将指向重构提交。
我在相同的问题中找到了应用于diff的解决方案。没有提到任何现有的非专有实现,但提到了一种追踪块移动的算法。
master
中更改中间行,但仍然存在冲突。 - loopbackbee