告诉git关注移动的内容(不仅仅是移动的文件)

时间:2013-12-12 10:31:59

标签: git merge diff merge-conflict-resolution

在重构源代码时,有时您需要在文件中移动大块文本,甚至移动到新文件。您创建一个分支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。没有提及任何现有的非专有实现,但提到了跟踪块移动的算法

2 个答案:

答案 0 :(得分:2)

不可能避免这种额外的努力,但那就是Git应该如何运作:

  

另一个从根本上聪明的设计决策是Git如何合并。   合并算法很聪明,但它们并不会过于聪明。   明确的决定是自动做出的,但是当有疑问时   由用户决定。这是应该的方式。你没有   想要一台机器为你做出决定。你永远不会想要它。   这是Git融合方法的基本见解:同时   Git是其他所有版本控制系统都在努力变得更聪明   幸福地自称为“愚蠢的内容管理者”,而且是   更好。

(来自Wincent Colaiuta's blog

答案 1 :(得分:1)

不幸的是,就我所知,你无法取代内置的git合并策略。这意味着您无法阻止冲突,但您可以使用智能工具来解决冲突。

这一个Semantic Merge看起来很有趣,它也可以是used by git