如何让Git理解移动文件和编辑文件是同一个文件?

时间:2017-12-12 16:29:22

标签: git git-merge

我有2个分支机构。在名为index.html的第一个文件中进行编辑和提交。在第二个这个文件编辑并移动到其他文件夹。   我可以让GIT理解(合并时)第一个分支的index.html是第二个分支的同一个文件“folder / index.html”。在我看来,问题是,当我将文件移动到新文件夹时,GIT首先将其删除,然后在新文件夹中创建它。   合并后,我将有两个更改的文件?

2 个答案:

答案 0 :(得分:2)

Git应该已经知道它们是同一个文件。在这里查看这个问题的答案。 Is it possible to move/rename files in git and maintain their history?。如果在移动的文件上键入git log,则会在移动后看到提交。以下命令应具有完整历史记录。

git log --follow folder/index.html

答案 1 :(得分:0)

编辑:我现在相信我今天早上误读了这个问题,你的分支中只有一个修改过的文件来自一个来源。在这种情况下,下面的描述是准确的,但告诉我们Git应该自己找到重命名的文件,只要它足够相似。如果没有,您可以添加-X find-renames=number参数并将其调整为git merge。您可能希望首先使用git diff(或更短的拼写--find-renames=number)运行一些手动-Mnumber,以找出哪些数字使Git看到合并库为{{1} }更改为重命名。

如果您在自己的分支中有两个修改过的文件,两者都来自单个源文件,Git的--ours将无法帮助您。您必须自己合并此文件,可能使用git merge。有关说明,请参阅下面的最后一部分。

git merge-file

有三个输入

这里的基本问题是git merge正好看三个提交。 1 我们需要这些提交的名称,而Git对这些名称并不十分一致:有时它们是{{ 1}}和git merge用于两个分支提示,有时它们是本地远程。我将使用 L ,用于左侧或本地或--ours R 用于右侧或远程或--theirs。第三次提交在某些方面是最重要的,但是Git自己发现了第三次提交:我们无法控制提交的提交。我们只选择 L R 提交。第三个提交是合并基础,简而言之, 2 它是两个分支首先回到一起的地方:

--ours

或:

--theirs

在这两个图中,标记为 o--...--o--o <-- L / ...--o--* \ o--o--...--o <-- R 的提交是合并基础。

1 为简单起见,我们假设这里有两个头的正常合并,只有一个合并库提交。包含两个或更多合并基础的交叉合并案例,以及具有两个以上头部的章鱼合并,使这一点复杂化,但不是我们关心的情况。

2 这有点短,但对大多数情况来说都足够了。

Git制作了两个差异

现在Git已找到合并基础 - L 提交只是我们当前的分支提示,而 R 提交是您在运行时指定的提交{{ 1}} - 并且有三个输入,Git运行...--o--o--o--*--o <-- L \ \ o--o--o--o <-- R 两次:

*

第一个git merge比较合并库提交中存储的所有文件 - 记住,每次提交都是所有文件的快照 - 存储在 L 中的所有文件,以便查看在git diff我们的变化。 git diff --find-renames base L # what we did git diff --find-renames base R # what they did 选项会对已重命名的文件进行此git diff检查,但不会检查复制的文件。重命名检测器以默认的“至少50%相似”运行(您可以在我的其他一些答案中找到有关此重命名检测器如何工作的详细说明:diff rename, copy, and break detectionsimilarity index),但您可以调整--ours的百分比。

第二个--find-renames使用 R 提交做同样的事情。

然后,git diff继续组合两组差异。

如果两个差异中的一个或两个检测到基础中的-X find-renames=n被重命名为 L R中的一个或两个中的某个其他路径< / em>提交,Git将采用其中一个重命名(并声明一个高级重命名/重命名冲突如果这两个提交都重命名为基本文件)。但是,再一次,没有打开复制检测的选项,Git只会在 L R 中的一个或两个中看到任何副本作为新文件。这可能会导致高级添加/添加冲突,如果它们都添加了;或者如果它只是在一次提交中添加,Git假定它应该添加到新提交中。

如果没有高级别冲突且没有低级别冲突,git diff通常会立即进行新的提交。您可以使用git merge来禁止此操作,并对工作树执行其他操作。 (结果是有些人称之为evil merge。你应该知道这一点,并且至少以某种方式标记提交,例如,在提交消息中。或者,进行正常合并,然后进行修正提交。对这个特殊问题不是完美的答案。)

手动合并

要手动合并复制的文件,解压缩合并基础版本 - 您可以找到合并基础提交哈希ID git merge-base - 并将两个提示版本分成三个普通文件,然后在其上使用git merge-file 。请注意,默认情况下,index.html将其输出写入三个输入中的一个 - 这可能是您想要的,因为HEAD或git merge版本已经在您的工作树中,在您的名下正在使用它,所以你真正需要做的是提取基础和--no-commit R 版本:

git merge-file

然后在完成合并后删除--ours--theirs版本。 (一如既往地检查生成的合并是明智的,因为Git只是遵循简单的一次一行规则来组合差异。)