Git 合并删除文件

JDM*_*JDM 2 git version-control merge github

这是第二次发生这种情况,当我进行合并时,我后来意识到正在合并的分支中的一些文件不再位于正在合并的分支中。

最新的例子是我们有一个功能分支,我一直在合并主开发分支中的更改,合并后我们丢失了很多文件,并且它们现在不存在于功能分支中。

  1. 为什么会出现这种情况?
  2. 获取这些文件的最佳方式是什么?我正在考虑手动添加它们。

以下是文件丢失时存储库的描述:

964495c是文件丢失的地方,它是远程分支与本地分支的合并。d1c457a 是从主开发分支到功能分支的合并。

当我对这两个分支进行比较时,我看到丢失的文件已被删除,但它们从未设置为删除。这不是我的合并,所以我不确定这是否是用户错误,但我需要找出将这些文件包含在我的功能分支中的最佳方法......

在此输入图像描述

tor*_*rek 5

第 1 部分的答案

\n\n

我这里没有足够的信息来告诉您发生了什么......但这里是如何查看git merge .... 从上图中我们可以看到,这964495c是一次合并,如果其父提交是d1c457a(黄色点和线),则这是一次合并。我们看不到它的另一个父提交 \xe2\x80\x94,另一个父提交位于紫色线的另一端。(我想,一条线是branch,dev另一条线是branch feature。)

\n\n

[编辑:根据评论,第一个父级是29a7b67(在分支上feature),第二个是(在预期的d1c457a分支上)。]dev

\n\n

首先git merge要做的就是找到“合并基础”。因此,在 shell 命令窗口中找到两个父 ID:

\n\n
$ git rev-parse 964495c^1\n29a7b67...\n$ git rev-parse 964495c^2\nd1c457a...\n
Run Code Online (Sandbox Code Playgroud)\n\n

(我在这里部分猜测,基于颜色,这d1c457a是第二个父级,即被合并的东西,而不是合并到\xe2\x80\x94的东西,并不是说它太重要了,合并无论哪种方式,结果都应该是相同的)。[编辑:确认]

\n\n

现在,使用上面生成的两个提交 ID,找到合并库。 为了简单起见,我假设1234567...每个评论生成的第一个命令是8967ae7...

\n\n
$ git merge-base 29a7b67 d1c457a\n8967ae7...\n
Run Code Online (Sandbox Code Playgroud)\n\n

您现在拥有三个提交 ID。让我们使用 shell 变量重新执行上述操作,这样我就不必再猜测提交 ID,因为符号名称可能会有所帮助:

\n\n
$ id_into=$(git rev-parse 964495c^1)\n$ id_from=$(git rev-parse 964495c^2)\n$ id_base=$(git merge-base $id_into $id_from)\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,shell 变量$id_base$id_from$id_into保存合并基础的提交 ID、合并源分支的尖端、1以及自身之前的提交的 ID (合并完成时分支964495c的原始尖端)。feature

\n\n

使用这些,我们可以git merge通过执行两个 s 来查看要求合并的内容git diff。(接下来的部分假设 Unix/Linux/Mac shell 重定向。)

\n\n
$ git diff -M50% $id_base $id_into > /tmp/existing_changes\n$ git diff -M50% $id_base $id_from > /tmp/new_changes\n
Run Code Online (Sandbox Code Playgroud)\n\n

第一个差异找出“这个分支上发生了什么,即,feature因为另一个分支dev与它分歧”。第二个差异找出“自从另一个分支dev与该分支分叉以来发生了什么,即feature”。

\n\n

然后该merge命令尝试将这两者结合起来。凡是有变化的地方dev

\n\n
    \n
  • 如果更改是添加新文件,请添加新文件(除非feature也添加了它:那么我们可能会遇到需要手动解决的冲突)
  • \n
  • 如果更改是重命名文件,请重命名该文件(除非feature已经重命名)
  • \n
  • 如果更改是删除文件,则删除该文件
  • \n
  • 如果更改是从文件中添加或删除某些行,请在此处执行此操作(除非feature已经存在,在这种情况下,请忽略更改;或者如果我们找不到具有相同内容的确切行,那么我们有冲突\xe2\x80\x94此冲突情况包括在 ) 中删除文件的情况feature
  • \n
\n\n

git merge 我已将应删除文件的情况加粗。如果合并源分支 ( dev) 自合并基础以来删除了该文件,git merge则会悄悄地从合并结果中删除该文件。

\n\n
\n\n

现在,话虽如此,如果进行合并的人使用--no-commit,或者存在冲突,则合并会在尽其所能后停止,并且进行合并的人有机会进行其他更改。在合并冲突的情况下,这当然是进行合并的人必须解决冲突的地方。然而,进行合并的人--no-commit即使没有冲突也可以到达这里。无论如何,此时,进行合并的人可以删除文件、添加文件和修改文件。当他或她(好吧,让我们使用“他们”:-))...当他们完成时,他们就是git commit结果,并且做出了提交964495c...

\n\n
\n\n

1dev至少,这是当时的尖端:dev从那时起可能已经增长了一点,就像feature从那时起实际上已经增长了一样。

\n\n

第 2 部分的答案

\n\n

不一定有单一的最佳方法来找回丢失的文件,但从特定提交中检出文件很容易。这里明显要使用的是29a7b67(也就是$id_from上面的提示,无论feature谁进行合并,都进行了合并):

\n\n
$ git checkout 29a7b67 -- path/to/file\n
Run Code Online (Sandbox Code Playgroud)\n\n

(列出多个文件,或一个或多个目录,以从该提交 ID 中获取更多文件或目录中的每个文件。)这会将文件按照其原来的状态放入工作树和索引中位于该提交 ID 处,以便下一个git commit会将它们包含在该状态中。

\n\n

(当然,git add如果需要,您可以编辑它们和结果以进行更改。)

\n