Covered in this article:
- Git cherry-picking commits from another branch
- Visualizing commits
Cherry-picking commits from another branch
Let’s say we have two branches: master and feature1, and we don’t want to merge all the feature1 commits to master, but rather cherry-pick only some of the commits.
In our case, we want the second recent one – 8ef7c70
| * f7ce3bf (feature1) add feature1 line to f2 - not for merging | * 8ef7c70 add feature1 line to f1 |/ * 98df444 (origin/master, origin/HEAD) add file f2 * 08e8f59 add line 2 * e46130a initial commit
So we run this command: git cherry-pick
$ git cherry-pick 8ef7c70 [master ccbbcef] add feature1 line to f1 1 file changed, 1 insertion(+)
If cherry-picking causes no conflict we get a straight commit and our working tree is clean
/repo1 (master) $ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) nothing to commit, working tree clean
Here’s the graph of the commits
/repo1 (master) $ git log --oneline --all --graph * ccbbcef (HEAD -> master) add feature1 line to f1 | * f7ce3bf (feature1) add feature1 line to f2 - not for merging | * 8ef7c70 add feature1 line to f1 |/ * 98df444 (origin/master, origin/HEAD) add file f2 * 08e8f59 add line 2 * e46130a initial commit
Git – branch merging commands, scenario two – cherry-picking a conflicting edit?
What happens when we are trying to cherry-pick a conflicting edit?
/repo1 (master) $ git commit -am "master changes to line 1 in f1" [master 9c759aa] master changes to line 1 in f1 1 file changed, 1 insertion(+), 1 deletion(-)
We’ll edit f1.txt on feature1 branch (f8d4b9a) and then the same line in the same file on master branch (9c759aa)
/repo1 (master) $ git log --oneline --all --graph * 9c759aa (HEAD -> master) master changes to line 1 in f1 * ccbbcef add feature1 line to f1 | * f8d4b9a (feature1) add feature1 line to f1 - line 1 for a conflict | * f7ce3bf add feature1 line to f2 - not for merging | * 8ef7c70 add feature1 line to f1 |/ * 98df444 (origin/master, origin/HEAD) add file f2 * 08e8f59 add line 2 * e46130a initial commit
Cherry-pick command fails and we will need to solve the conflict manually
/repo1 (master) $ git cherry-pick f8d4b9a error: could not apply f8d4b9a... add feature1 line to f2 - line 1 for a conflict 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'
Note that Git is telling you that you are still in CHERRY-PICKING mode, on master branch
/repo1 (master|CHERRY-PICKING) $ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) You are currently cherry-picking commit f8d4b9a. (fix conflicts and run "git cherry-pick --continue") (use "git cherry-pick --abort" to cancel the cherry-pick operation) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: f1.txt
Now we open f1.txt on master branch, edit the lines we need and save. After resolving the conflict, we mark the corrected file with ‘git add ‘
/repo1 (master|CHERRY-PICKING) $ git add f1.txt
And then we commit the resolved change in f1.txt
/repo1 (master|CHERRY-PICKING) $ git commit -m "resolved cherry-picking conflict in f1" [master 7cea11c] resolved cherry-picking conflict in f1 1 file changed, 1 insertion(+), 1 deletion(-)
And this is our new commit log on master, with the feature commit cherry-picked
/repo1 (master) $ git log --oneline --all --graph * 7cea11c (HEAD -> master) resolved cherry-picking conflict in f1 * 9c759aa master changes to line 1 in f1 * ccbbcef add feature1 line to f1 | * f8d4b9a (feature1) add feature1 line to f2 - line 1 for a conflict | * f7ce3bf add feature1 line to f2 - not for merging | * 8ef7c70 add feature1 line to f1 |/ * 98df444 (origin/master, origin/HEAD) add file f2 * 08e8f59 add line 2 * e46130a initial commit