Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cherry pick shows conflicts in lines not touched by the commit?

Tags:

git

egit

When I first read about git cherry-pick I thought of it as applying the changes introduced by a commit as a patch to HEAD in a new commit. My first several usages were compliant with that perception.

Later, I tried to cherry pick a very simple commit from a diverged branch:

git cherry-pick ab797f0c

To my surprise, I got several conflicts in lines that were not touched by the commit!!! the commit was very simple, 2 lines changed in a single file.

I tried EGit which showed a note: "EGit uses interactive rebase mechanics for cherry picking, which is different from regular Git ..." but i got the same or similar conflicts!

I tried:

git diff ab797f0c^ ab797f0c |patch -p1

Which worked perfectly and handled hunk offsets.

Why git/EGit had problems cherry picking a commit that can be easily applied by patch? How cherry pick really works in git and how is it different in EGit?

Update:

Based on advice from Andrew, I tried to reduce the problem to a simple repository. Here it is: https://github.com/alhashash/cherry-test

cherry-test commits

I'm on test and trying to cherry-pick Cherry. git cherry-pick Cherry produces a lot of conflicts unrelated to the commit while git diff Cherry^ Cherry |patch -p1 worked fine!

EGit gives similar conflicts as git.

Update2:

It appears that my reduced example repository shows the problem only with EGit. git showed a conflict in one of the picked commit huncks which is expected.

I'll try to replicate the issue for git in a simple repository. The problem I had was on oddo OCB forked repo I was on commit fb978c60 and trying to cherry pick ab797f0

like image 954
Mohammad Alhashash Avatar asked Nov 09 '14 20:11

Mohammad Alhashash


1 Answers

It's because git cherry-pick is performing a 3-way merge underneath the hood, and commit C is modifying the same area as commit B. The diff technique works because patch will ignore up to 2 lines of the context by default, where as git cherry-pick does not. If you try again with patch -p1 -F0, patch will fail to apply it too.

The diff trick may have worked in this case, and may have even correctly done what you want, but it doesn't in all cases. git cherry-pick is taking a more pragmatic approach and alerting you to changes in the area to let you decide how those changes should be brought together. Depending on the situation, a different diffing algorithm can reduce the conflicts (or make them more meaningful). You can do this by using the -X option (such as -Xpatience to use the patience algorithm). None of this works in this specific case though.

All of that said, if you find you are cherry-picking commits often and end up with the same conflicts often, rerere can be your friend. You can enable it globally with git config --global rerere.enabled. It will record the resolution that you made, and if you encounter it again, it will automatically apply it. The cherry-pick will still stop with the previous resolution applied, but it's a quick review and a --continue away to make sure it has done the right thing.

like image 177
John Szakmeister Avatar answered Nov 15 '22 11:11

John Szakmeister