Git cherry-pick doesn't just pick the difference in commit

I have two branches: A and B

  • A history of fixation: a <- b <- c ;
  • B history of fixation: a <- h <- i ;

Suppose there is only one file.

  • In commit B I add some texts, such as "foo".
  • In commit c I add some texts, such as "bar".
  • Then I git cherry-pick c on branch B I thought cherry-pick would pick the changes in c for branch B However, it will add both foo and bar to branch B This is obviously not what I want.

Therefore, cherry-pick will select all changes to those files that were affected in commit c , since precestor commit A It is right? What if I only want to select diff from B to c and apply it to i ?

Update exact steps

  • Initialize git repo;
  • Add the test.txt file and run the first commit init commit command. test.txt now:

     first line second line 
  • Create a new dev branch, but stay in the master branch;

  • Add added in commit b to the file and run commit B test.txt now:

     first line added in commit b second line 
  • Add added in commit c to the file and issue the commit c command. test.txt now:

     first line added in commit b added in commit c second line 
  • The dev branch opens and issue commit h . test.txt now:

     first line second line adding by commit h 
  • git cherry-pick <commit c SHA1 ID> to commit-pick commit c to commit h .

  • Conflict Report:

     index 6a8dc57,594c6ec..0000000 @@@ -1,4 -1,4 +1,9 @@@ first line ++<<<<<<< HEAD ++======= + added in commit b + added in commit c ++>>>>>>> 06ce9b1... commit c adding another line second line + +adding by commit h 
  • Cm? cherry-pick also adds changes to commit B

Thanks!

+7
git cherry-pick
source share
2 answers

git cherry-pick tries to execute only one commit. But he does this by applying a patch that requires some context. The change made in commit C is very close to the change made by commit b, so you get a conflict - it cannot just find the right place where the change should be applied. And when you have a conflict, you also get some conflict context, which is at least part of your commit B.

Here's how it will work without conflict:

 $ git init $ cat > f line1 line2 line3 $ git add f $ git commit -a -m "initial" # Edited to add a line in the beginning of f $ cat f Commit b line1 line2 line3 $ git commit f -m "B" # Edited to add a line in the end of f $ cat f Commit b line1 line2 line3 Commit c $ git commit f -m "C" $ git checkout HEAD^^ $ git cherry-pick master $ cat f line1 line2 line3 Commit c 
+4
source share

What if I only want to select diff from b to c and apply it to i?

You can find / write a diff file between two commits ( c..d ). Then apply this in your current branch.

 $ git checkout <B-branch> # write the diff in a file named 'change.patch' (root directory) $ git diff <b-commit> <c-commit> <file-name> >> ~/changes.patch $ git apply ~/changes.patch # apply the changes $ git add . # merge the changes to i (previous commit) $ git commit --amend -m 'Apply the diff of b and c' $ git push -f origin HEAD # force(-f) push since history is changed 
0
source share

All Articles