问题描述
我想知道为什么 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 找到提交 P
的父 C
:
- commit
P
现在是合并基础; -
ours
提交是 当前 (HEAD
) 提交;和 -
theirs
提交是提交C
。
P
和 HEAD
之间的区别在于相关文件已被完全删除。 P
和 C
的区别在于文件内容被修改了。
对于标准合并算法 (git-merge-recursive
),这是一个高级或树级冲突:修改/删除冲突。这是一个无法用 -X ours
或 -X theirs
解决的合并冲突。因此合并会在中间停止,留下必须解决的合并冲突。
解决合并冲突并运行 git cherry-pick --continue
以完成挑选。您解决此合并冲突的方式取决于您; larsks answer 中的 git checkout
命令很好,或者您可以使用 git checkout --theirs test
和 git add test
。请注意,当使用 git checkout --ours
(在这种情况下不适用)和 git checkout --theirs
时,Git 不会将冲突标记为已解决,但是当使用 git checkout CHERRY_PICK_HEAD
(或原始哈希 ID)时,Git does 标记冲突已解决。这是由于 git checkout
实现中的一个怪癖。