Git Tip: Cherrypicking out of a bind!
There are times I forget to create a new branch when I'm working on a new feature and only notice the mistake when push my first commit, but just today one of my co-workers (Jonathan) showed me some neat git tricks that helped me correct my mistake. In this article I'll show how to use cherrypicking to get out of a bind.
The Setup
For the purposes of this blog post, we'll set up a contrived example by creating a git repo and adding an empty Readme.md file
and making this our initial commit. Running git log
should now only display 1 commit:
commit d7d597f0908c54713bfc83e078f7bc71f069e681
Author: Roberto Guerra <xxx@xxxx.xxx>
Date: Fri Mar 24 07:40:14 2017 -0600
We create a branch and add a header to our Readme and commit:
git checkout -b branch-1
--edit our Readme--
git add .
git commit -m "Added header"
Our git log should now have the following commits:
commit bcee75824ed9ffd124d5f1fadc6995cde00757dd
Author: Roberto Guerra <xxx@xxx.xxx>
Date: Fri Mar 24 07:44:03 2017 -0600
Added header
commit d7d597f0908c54713bfc83e078f7bc71f069e681
Author: Roberto Guerra <xxx@xxx.xxx>
Date: Fri Mar 24 07:40:14 2017 -0600
Initial Commit
We can pretend that this is a complete feature and that we pushed this to origin and opened a PR.
The Mistake
Frequently after I do this, I start working on a new feature branch and assume I created a new branch from master.
But I normally only realize that I'm still on the old branch after I make my first commit (and push to origin). Lets simulate
this mistake by adding another paragraph header to the readme and commiting it in branch-1
. Now our logs should look similar
to this:
commit c1086ef12918f774075f1d269f70b205e2730ee2
Author: Roberto Guerra <uris77@gmail.com>
Date: Fri Mar 24 07:48:43 2017 -0600
Added Body
commit bcee75824ed9ffd124d5f1fadc6995cde00757dd
Author: Roberto Guerra <xxx@xxx.xxx>
Date: Fri Mar 24 07:44:03 2017 -0600
Added header
commit d7d597f0908c54713bfc83e078f7bc71f069e681
Author: Roberto Guerra <xxx@xxx.xxx>
Date: Fri Mar 24 07:40:14 2017 -0600
Initial Commit
The Fix
When this happens I normally want to place the latest commit in a new branch and continue working from there, while also deleting
the latest commit from the original branch. We can accomplish this by using git's cherry-pick
.
Copy the hash of the commit we want to remove. In this example it is c1086ef12918f774075f1d269f70b205e2730ee2.
Checkout master (git checkout master).
Create a new branch (git checkout -b branch-2).
Cherry pick the commit (git cherry-pick c1086ef12918f774075f1d269f70b205e2730ee2).
We may decide to push this branch to master (git push -u origin HEAD).
Checkout the old branch (git checkout -b branch-1).
Remove the latest commit (git reset --hard HEAD~1). At this point if we print our git logs, it should only contain the first two commits we made:
commit bcee75824ed9ffd124d5f1fadc6995cde00757dd
Author: Roberto Guerra <xxx@xxx.xxx>
Date: Fri Mar 24 07:44:03 2017 -0600
Added header
commit d7d597f0908c54713bfc83e078f7bc71f069e681
Author: Roberto Guerra <xxx@xxx.xxx>
Date: Fri Mar 24 07:40:14 2017 -0600
- Force push to origin so it is also removed there (git push -f).
Git provides tools for manipulating commits and branches that allow us to fix most of our blunders. reset
and cherry-pick
have proven to be useful commands that often help me correct my mistakes.
TLDR;
git log
Copy the hash of the last commit (the one that doesn't belong in this branch).
git checkout master
git checkout -b new-branch
git cherry-pick the-hash-copied
git push -u origin HEAD
git checkout to-original-branch
git reset --hard HEAD~1
git push -f

Roberto Guerra
Roberto Guerra is a developer living in the Caribbean.
In his spare time, he likes to read fantasy books and goof around with his dogs. He also started learning to play the classical guitar late in life. His current tech interests are Go, serverless and MacOS development with Swift.