挑选一个删除文件的提交:cherry picking

3

我需要将几个仓库(每个仓库都是从 TFS 转换而来)合并成一个。为了做到这一点,我使用 git cherry-pick 命令,它对一些提交有效,但对其他提交无效:

$ git status
# On branch master
nothing to commit, working directory clean
$ git diff-tree --no-commit-id --name-only -r e2d8405
Libraries/IFileTransformer/ITransformer.cs
Libraries/IFileTransformer/IFileTransformer.csproj
Libraries/IFileTransformer/IFileTransformer.csproj.vspscc
Libraries/IFileTransformer/Properties/AssemblyInfo.cs
$ git cherry-pick e2d8405
error: could not apply e2d8405... TFS changeset 2836
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
$ git status
# On branch master
# You are currently cherry-picking.
#   (fix conflicts and run "git commit")
#
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       deleted by them:    Libraries/IFileTransformer/ITransformer.cs
#       deleted by them:    Libraries/IFileTransformer/IFileTransformer.csproj
#       deleted by them:    Libraries/IFileTransformer/IFileTransformer.csproj.vspscc
#       deleted by them:    Libraries/IFileTransformer/Properties/AssemblyInfo.cs
#
no changes added to commit (use "git add" and/or "git commit -a")
$

我要如何找出问题所在?"them"是指谁?看起来e2d8405提交删除了这四个文件。如果这些文件存在(它们确实存在),那么应用该提交的问题在哪里?

$ git checkout e2d8405^
Note: checking out 'e2d8405^'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 48b5b2f... TFS changeset 2835   renamed namespace installutils to
 utils
$ md5sum IFileTransformer.csproj
9f9851dc9db3bddd1e6920631fa14e8b *IFileTransformer.csproj
$ git checkout master
Previous HEAD position was 48b5b2f... TFS changeset 2835   renamed namespace ins
tallutils to utils
Switched to branch 'master'
$ md5sum IFileTransformer.csproj
9f9851dc9db3bddd1e6920631fa14e8b *IFileTransformer.csproj

1
"Them" 是您要挑选的提交。"Us" 是您要将其挑选到的分支。 - Fred Foo
谢谢,这正是我怀疑的:提交删除了这四个文件。但是这个操作有什么问题呢...? - Tomasz Grobelny
3个回答

3

虽然该提交删除了这些文件,但是您进行了修改,这些修改在已删除的版本中不存在。由于分支修改了这些文件并将其删除之间存在冲突,您需要解决此冲突,指示您愿意放弃更改并应用删除(git rm ...)。完成后,git commit以创建挑选的提交。


我该如何找出这些更改是什么?在我看来,主干分支上的文件和之前的提交是相同的(添加了命令和结果以显示问题)。 - Tomasz Grobelny
有可能检查它们会丢弃空格更改。尝试使用 git diff HEAD e2d8405^ Libraries/IFileTransformer/ITransformer.cs Libraries/IFileTransformer/IFileTransformer.csproj Libraries/IFileTransformer/IFileTransformer.csproj.vspscc Libraries/IFileTransformer/Properties/AssemblyInfo.cs 或者 git log -p HEAD...e2d8405^ <same files> 来查看提交记录。 - Joe
实际上,这些文件中的行结尾是不同的。 - Tomasz Grobelny
好的,现在我知道问题出在哪里了,但是我该如何实际解决它?我该如何使挑选樱桃(cherry-picking)忽略空格差异? - Tomasz Grobelny

1
运行 git mergetool 命令,它会告诉你为什么出现了删除文件的冲突,这个文件很可能在本地被修改并且在 "them" 提交中被删除。它想让你决定是保留修改后的版本还是删除这些文件。
然后你可以选择针对这些文件采取的操作。

-1
git合并的工作方式大致如下:
对于每个要合并的文件,找到包含该文件的最新提交,在将要合并的两个分支中都存在。然后搜索要合并的每个分支,查找任何后续更改,这些更改将仅存在于其中一个分支中。
  • 如果两个分支都没有这样的更改,请不要更改文件
  • 如果一个分支有文件更改而另一个分支没有,则保留有更改的分支
  • 如果两个分支都进行了更改,那么git将无法自动合并(哪个更改应该保留,哪个应该丢弃-需要手动干预)
您遇到的情况是最后一种情况,即在一个分支中删除了文件,但在另一个分支中,在两个分支上次合并之后对其进行了更改。
  A 1* B
   / \
  2   3
  |   |
  |   4*
  5*  |
  |   |

在这里,数字代表提交次数,*表示我们感兴趣的文件所包含的更改已经被提交。因此,在第一次提交时,我们还没有分支,这意味着该提交是基础提交,也是两个分支中都存在的最新提交。在分支后,每个分支都添加了一个提交,但都不包括所涉及的文件。在此时合并时,该文件仍保持在提交1中的状态。然后,在第4次提交时,对B分支中的文件进行了更改。如果此时将B分支合并到A分支中,则提交4中对文件所做的更改将合并到A分支中,因为它是最新的提交,并且在基础提交(1)之后,A分支中没有对该文件进行更改。但是,在第5次提交时,文件也在A分支中进行了更改。现在,如果我们尝试合并(无论哪种方式都会产生相同的结果),我们将遇到冲突,因为该文件在两个分支中(基础提交后)都已更改,而Git无法选择其中一个作为“正确”的版本,因此需要您自己决定。
检查不包括删除的分支中文件的历史记录,然后您可能会发现一个提交在该分支中,而不是删除它们的分支中。

自动合并是在两个不同的文件及其共同祖先上应用三路合并算法,用于逐行合并更改。当两个分支都发生更改时使用它。仅当自动合并无法产生输出时才需要手动干预。如果只有一侧发生更改,则完全不需要自动合并。 - Edward Thomson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接