我正在一个删除了一些文件夹的分支上工作。与此同时,在 master 分支上,所有根文件夹都已重命名,因此所有文件(包括我已删除的文件)的路径都已重命名。
当我尝试 merge 时,所有已删除(在我的分支上)和重命名(在 master 上)的文件夹的所有文件都发生冲突。我列出了这些(1000+)个文件,这些文件在 git status 的未 merge 路径中显示如下:
added by them: FolderRenamed/File1.ext
added by them: FolderRenamed/File2.ext
在这种情况下,当我尝试在我的分支中 merge master 时,我想从“他们的”版本恢复它们(尽管您可能希望我想做相反的事情,并确认文件删除;这将是与“我们的”而不是“他们的”相同的概念)。
我以为我可以简单地为每个文件调用以下命令:
git checkout --theirs FolderRenamed/File1.ext
但似乎在文件上调用此命令不会实现任何更改。我的文件仍在“merge 路径”列表中。
有人可以帮我确定我做错了什么吗? git checkout 是否因为本地版本已被删除而无法按预期工作?
最佳答案
TL;DR:您只需要 git add
他们。
更长
When I attempt to merge I get a conflict on all the files of all the folders that have been both deleted (on my branch) and renamed (on master) ...
是:当你运行时,例如:
git checkout branch
git merge master
git :
HEAD
又名 branch
:这些通过哈希 ID 选择一个特定的提交,这也是您现在在索引和工作树中的提交),也称为本地或 --ours
,但我只是称它为 L(左/本地); master
),也称为远程、其他和 --theirs
,但我只是称之为 R(右/远程); (请注意,如果您 checkout
master
并运行 git merge branch
,您只是在过程的这一部分交换 L 和 R。)然后,Git 实际上运行了两个
git diff
s 启用重命名检测:git diff --find-renames B L > /tmp/b-vs-l.patch
git diff --find-renames B R > /tmp/b-vs-r.patch
结果是你在 L 中从 B 开始所做的所有事情的列表,以及他们从同一个 B 开始在 R 中所做的一切。然后 Git 将这些更改结合起来。
如果您重命名了一个文件并且他们删除了“相同”的文件(如重命名检测所检测到的),则这是重命名/删除冲突。如果他们重命名了一个文件而你删除了它,你会遇到同样的冲突。无论哪种方式,Git 都有冲突。
在冲突的特殊情况下(但不是在普通情况下),Git 将在您的索引中保留每个文件的所有三个版本:来自 B 的一个,Git 在索引中保留为“阶段 1”;来自 L 的那个,Git 在索引中作为“阶段 2”或
--ours
留在索引中;和来自 R 的一个,Git 在索引中作为“阶段 3”或 --theirs
留在索引中.这些编号较高的阶段文件是 Git 记住您正处于 merge 冲突中的方式。通常,索引中的所有文件都处于“零阶段”。如果 Git 能够自己解决冲突,它会删除三个更高的阶段,只留下一个阶段零已解决的文件。
您的工作树中的文件(大部分)独立于索引中的文件,当然您的工作树没有阶段插槽编号。只能有一个
somepath/file1.ext
.在重命名/删除冲突的情况下,基本文件有第 1 阶段条目,--ours
有第 2 阶段或第 3 阶段条目。或 --theirs
文件。另一个阶段插槽(分别为 3 或 2)留空。 git status
命令将其显示为 added by us
(1 和 2 已占用,3 空)或 added by them
(1 和 3 已占用,2 为空)。运行
git checkout --ours
告诉 Git 将 stage-slot-2 版本复制到工作树。运行 git checkout --theirs
告诉 Git 将 stage-slot-3 版本复制到工作树。在任何一种情况下,stage-slot-1 条目都不会发生任何变化,而 stage-slot-0 条目保持为空。运行
git add
告诉 Git 将文件从工作树复制到阶段零插槽,完全清除剩余的插槽。该文件现已解决。由于 Git 将重命名的文件保留在工作树中(在新名称下),因此在这种情况下您需要做的就是
git add
重命名的文件。但这不是唯一的方法
如果您运行
git checkout commit-specifier -- path
, Git 提取给定的 path
来自给定的 commit-specifier
.当 Git 执行此操作时,它会将路径复制到索引的零槽中。这会清除该路径的任何插槽 1-3 条目,因此从特定提交 check out 文件的副作用是这会解析文件。这与
git checkout --ours
不同和 --theirs
因为那些是从现有索引条目中提取的,所以它们不会写入插槽零。因此你也可以使用
git checkout MERGE_HEAD -- paths
将重命名的文件提取为其重命名的名称,解决过程中的 merge 冲突。
关于git - 如何解决已在第一个分支中删除并在第二个分支中重命名的文件的 merge 冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48793631/