git - 如何解决已在第一个分支中删除并在第二个分支中重命名的文件的 merge 冲突?

标签 git

我正在一个删除了一些文件夹的分支上工作。与此同时,在 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(右/远程);
  • 找到这两个提交之间的 merge 基础。这是最近的共同提交。我称这个 B 为基础。

  • (请注意,如果您 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/

    相关文章:

    eclipse - 如何将 .txt.gz 文件推送到 git

    git - 这样的工具有什么问题: texlive-latex-base texlive-latex-recommended latex-xcolor pgf latex-beamer prosper texlive tipa?

    git - 定义具有相同名称的 git 别名以 stash 原始命令

    git - 如何让 Git 在控制台窗口中正确显示 UTF-8 编码的路径名?

    git - 使用 Git 的编码器协作最佳实践

    git - 远程 : Invalid username or password

    git - 如何确定谁将特定本地标签推送到远程 Git 存储库

    git - 停止将代码直接 checkin VSTS 中的 master 分支的权限

    git - git push origin development和git push origin HEAD :development的区别

    git - 在没有任何工作树的情况下使用 Git