无法挑选提交更改不存在的文件

Cannot cherry-pick commit changing not-existing file

我想知道为什么 git 不允许挑选对不存在的文件进行更改的提交。 我的理解是提交代表工作目录的完整快照。因此,挑选一个包含当前不存在的文件的提交应该简单地创建该文件 - 但我可以看到情况并非如此。

下面是重现我正在谈论的情况的几个命令。

$ git init
Initialized empty Git repository in /home/mzakrze/workspace/tmp/.git/
$ echo "Hello world!" > first_file; git add first_file; git commit -m "Init commit"
[master (root-commit) 7f9478a] Init commit
 1 file changed, 1 insertion(+)
 create mode 100644 first_file
$ echo "Fox jumps over the layz dog" > test; git add test; git commit -m "Commit with a typo"
[master 776387b] Commit with a typo
 1 file changed, 1 insertion(+)
 create mode 100644 test
$ echo "Fox jumps over the lazy dog" > test; git add test; git commit -m "Fix typo"
[master 9ea19df] Fix typo
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git log 
commit 9ea19dfe2597b28eb576e2682e745de3da74733f
Author: mzakrze <xxxxxx@gmail.com>
Date:   Sun Apr 11 17:01:13 2021 +0200

    Fix typo

commit 776387b563edba9df2a12c5d1a2fd5bffb10c643
Author: mzakrze <xxxxxx@gmail.com>
Date:   Sun Apr 11 17:00:53 2021 +0200

    Commit with a typo

commit 7f9478a83e3938bf57552c1b90ddc7322b1bf315
Author: mzakrze <xxxxxx@gmail.com>
Date:   Sun Apr 11 16:59:04 2021 +0200

    Init commit
$ git reset --hard 7f9478a83e3938bf57552c1b90ddc7322b1bf315
HEAD is now at 7f9478a Init commit
$ git cherry-pick 9ea19 # cherry-pick "Fix typo"
error: could not apply 9ea19df... Fix typo
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'

INB4:我不是在寻找“解决方案”,我只是想了解为什么 git 认为这是一个冲突。

如果您查看 cherry-pick 命令的文档(参见 git cherry-pick --help),描述是“应用一些现有提交引入的更改”。换句话说,这会查看选定的提交及其父项,计算两者之间的差异,并尝试将该更改应用到当前分支。

您尝试提交的更改cherry-pick影响了一个不存在的文件,因此无法应用。

如果您只是想要源代码提交中存在的文件,您可以:

git checkout 9ea19 test

请记住,cherry-pick 在技术上是一种三向合并。您 运行 git cherry-pick C,对于某些提交 C——通常由哈希 ID 指定——并且 Git 找到提交 C 的父级 P

  • 提交 P 现在是 合并基础;
  • ours 提交是 当前 (HEAD) 提交;和
  • theirs 提交是提交 C

PHEAD 的区别在于,有问题的文件已被完全删除。 PC的区别是修改了文件内容

对于标准合并算法(git-merge-recursive),这是一个高级别树级别冲突:一个modify/delete冲突。这是无法用 -X ours-X theirs 解决的合并冲突。因此,合并在中间停止,给您留下必须解决的合并冲突。

解决合并冲突,运行git cherry-pick --continue完成cherry-pick。解决此合并冲突的方式取决于您; 中的git checkout命令就可以了,或者你可以使用git checkout --theirs testgit add test。请注意,当使用 git checkout --ours(在这种情况下不适用)和 git checkout --theirs 时,Git 不会标记冲突已解决,但是当使用 git checkout CHERRY_PICK_HEAD(或原始哈希 ID)时, Git 是否 标记冲突已解决。这是由于 git checkout.

的实现中的一个怪癖