cherry-picking commit - is commit a snapshot or patch?

十年热恋 提交于 2019-12-12 17:23:57

问题


I have a question related to cherry-picking commits and conflicts.

The 'Pro Git' book explains that commits are kind of snapshots and not patches/diffs.

But cherry-picking commit may behave as it was a patch.


Example below, in short:

  1. create 3 commits, each time edit first (and single) line of the file

  2. reset the branch to first commit

  3. test1 : try to cherry-pick third commit (conflict)

  4. test 2: try to cherry-pick second commit (OK)


mkdir gitlearn
cd gitlearn

touch file
git init
Initialized empty Git repository in /root/gitlearn/.git/

git add file

#fill file by single 'A'
echo A > file && cat file
A

git commit file -m A
[master (root-commit) 9d5dd4d] A
 1 file changed, 1 insertion(+)
 create mode 100644 file

#fill file by single 'B'
echo B > file && cat file
B

git commit file -m B
[master 28ad28f] B
 1 file changed, 1 insertion(+), 1 deletion(-)

#fill file by single 'C'
echo C > file && cat file
C

git commit file -m C
[master c90c5c8] C
 1 file changed, 1 insertion(+), 1 deletion(-)

git log --oneline
c90c5c8 C
28ad28f B
9d5dd4d A

test 1

#reset the branch to 9d5dd4d ('A' version)
git reset --hard HEAD~2
HEAD is now at 9d5dd4d A

git log --oneline
9d5dd4d A

#cherry-pick 'C' version over 'A'
git cherry-pick c90c5c8
error: could not apply c90c5c8... C
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'

#the conflict:
cat file
<<<<<<< HEAD
A
=======
C
>>>>>>> c90c5c8... C

test 2

#same for 'B' - succeeds
git reset --hard HEAD
HEAD is now at 9d5dd4d A

git cherry-pick 28ad28f
[master eb27a49] B
 1 file changed, 1 insertion(+), 1 deletion(-)

Please explain why test 1 failed (I could imagine the answer if commits were patches, but snapshots?)


回答1:


The Pro Git book is correct: a commit is a snapshot.

You are also correct, though: git cherry-pick applies a patch.

How can this be? The answer is that when you cherry-pick a commit, you also specify which parent commit to consider, with the -m parent-number argument. The cherry-pick command then generates a diff against that parent, so that the resulting diff can be applied now.

Should you choose to cherry-pick a non-merge commit, there is only one parent, so you don't actually pass -m and the command uses the (single) parent to generate the diff. But the commit itself is still a snapshot, and it's the cherry-pick command that finds the diff of commit^1 (the first and only parent) vs commit and applies that.



来源:https://stackoverflow.com/questions/27760257/cherry-picking-commit-is-commit-a-snapshot-or-patch

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!