假设我在文件A中有函数X,我想将该函数移动到文件B.与此同时,其他人在文件A中对函数X进行了更改。
在合并这两个更改时,git是否会执行任何特殊操作?它是否会识别相同的功能被移动到文件B并在那里应用更改?或者我们最终会丢失更改或在文件A和B中有两个相同功能的副本?
我发现的大多数关于在git中移动代码的文章主要是指重命名整个文件而不是文件内的代码块。我找到的最近的是blurb from Linus at kerneltrap:
使用git时,整个'保持 代码运动与变化分开 有一个更根本的原因: git可以跟踪代码移动(再次, 无论是移动整个文件还是只是移动文件 文件之间的功能)和做一个 'git blame -C'实际上会跟着 文件之间的代码移动。确实如此 通过相似性分析,但它 确实意味着,如果你们两个都移动了 代码和同时更改它, git看不到'哦,那个功能 最初来自那个其他文件', 现在你的注释变得更糟了 关于代码实际来源的地方。
所以看起来git会认识到代码被移动到了其他地方,但并没有真正说明合并过程中会发生什么。
答案 0 :(得分:8)
我不认为以前的答案在一般情况下是正确的,因为git并不真正关心文件 - 文件名被用作某些启发式的基础,但git对内容的思考方式不是完全围绕文件的想法。与其他VCS不同,git跟踪内容,在这种情况下,内容恰好已经移动,但它是相同的内容。
因此,git应该能够处理分支之间的合并,即使文件已被重命名,或者代码在文件之间移动,因此根据您的具体操作,它可能会处理合并。
只要对X的更改不会导致合并冲突(如果您更改了原始版本和重命名版本可能会发生这种情况),则X已被移动到B应该没关系,合并结果应该包含两个变化的结果。如果 出现问题,则表明git未正确跟踪代码移动。
在实践中,之前的答案可能是基于检测机制失败时的个人经验,在这种情况下https://git.wiki.kernel.org/index.php/GitFaq#How_to_manually_resolve_conflicts_when_Git_failed_to_detect_rename.3F可能会有所帮助。
答案 1 :(得分:7)
不,git不会做这种程度的改变。移动整个文件时会注意到;因此,例如,如果您移动了文件,删除了其中的所有内容,则可能会有机会获取更改。但它不会对每个子文件或任何类型的重构进行更改。
答案 2 :(得分:2)
我认为AlBlue是正确的,而不是Nye。
在我的简单测试中,git 1.7.0.5无法自动合并两个分支,其中一个分支将一行插入一个函数,另一个分支将该函数移动到同一文件中的新位置。似乎git并不跟踪小于文件的内容块。
要解决合并冲突,进行合并的人必须知道这两个更改的工作原理以及它们应如何组合。
另见git merge: apply changes to code that moved to a different file
答案 3 :(得分:0)
我认为真实情况要复杂得多,但根据我的经验,git可以很好地处理这种3路合并。
例如:
分支A中的文件的一个功能被移动到同一文件中的另一个位置,同时创建一个分支B来保存它。分支B和分支A之间的区别仅在于同一文件中的代码位置更改。
分支C改变了这个功能。
所以,如果你这样做:
$ git rebase --onto B A C
它会自动将分支C的变化合并到分支B中该函数的新位置。