【问题标题】:Telling git to follow moved content (not simply moved files)告诉 git 跟随移动的内容(不仅仅是移动的文件)
【发布时间】: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


【解决方案1】:

无法避免这种额外的努力,但话又说回来,这就是 Git 应该如何工作的:

另一个根本上明智的设计决策是 Git 如何进行合并。 合并算法很聪明,但他们不会尝试太聪明。 明确的决定是自动做出的,但当有疑问时 由用户决定。这是应该的方式。你不 想要一台机器为您做出这些决定。你永远不会想要它。 这就是 Git 合并方法的基本见解:虽然 每个其他版本控制系统都在努力变得更智能,Git 是 愉快地自我描述为“愚蠢的内容管理员”,它是 对它更好。

(来自Wincent Colaiuta's blog

【讨论】:

    【解决方案2】:

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

    这个Semantic Merge看起来很有意思,也可以是used by git

    【讨论】:

    • 我已经在示例存储库上尝试过 SemanticMerge。首先,在 linux 上,它引入了 80MB 的依赖项——大量来自 plasticscm 的包和看起来是单声道的包。必须使用git mergetool 手动完成合并,并且该工具需要交互(“Hit return to start”)并使用 GUI(不能从 CLI、AFAICT 运行它)。最后,它只是未能合并我的示例中的冲突,“发现解析错误,树可能不一致”。我不确定该工具是否真的在做任何事情,因为我得到一个错误“对象引用未设置为对象的实例”。
    • 公平地说,我在 ubuntu 12.04 LTS (Precise Pangolin) 上试过,不一定支持 (we guarantee support only for Debian 6.0, but this repository may be targeted also to newer Debian versions (like 7.0, for instance) and Ubuntu distributions (especially LTS versions))
    猜你喜欢
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 2022-08-09
    • 1970-01-01
    相关资源
    最近更新 更多