Cherry picking from Git repository branch pull request
Ever worked on a Git repository involving multiple people with an individual that committed a crime to the repository where you need to scavenge the working commit and discard the non-working ones?
I certainly have done something like this before and let me share this with you on how you can cherry-pick or scavenge the working bits. In order to elaborate this process better, I have provided a simple scenario that you can try and fix it yourself.
Scenario
Imagine Mickey Mouse created a branch and created a CONTRIBUTING.md
markdown
file with his name listed under the CONTRIBUTORS
header using PowerShell.
1
2
# Create a new branch to work on
git checkout -b Mickey_Mouse_Branch
1
2
3
4
5
6
7
8
9
10
11
12
# Create content for a new markdown file
# using PowerShell
"# CONTRIBUTORS" | `
Out-File `
-PSPath CONTRIBUTING.md `
-Encoding utf8 ;
"- Mickey Mouse" | `
Out-File `
-PSPath CONTRIBUTING.md `
-Encoding utf8 `
-Append ;
1
2
3
4
5
6
7
8
# Add and stage the new file
git add CONTRIBUTING.md
# Commit the changes with a message
git commit -m "Added Mickey Mouse to CONTRIBUTORS list"
# Push the changes to remote branch
git push -u origin Mickey_Mouse_Branch
And Minnie Mouse came along, listing all remote branches to check if Mickey
Mouse’s new branch has been created and found Mickey_Mouse_Branch
in the
list.
1
2
# List the remote branches
git branch -rv
Output:
1
2
3
origin/HEAD -> origin/master
origin/Mickey_Mouse_Branch 9d96c20 Added Mickey Mouse to CONTRIBUTORS list
origin/master f7ac036 changes made to master branch
She checked out Mickey_Mouse_Branch
and found the new CONTRIBUTING.md
markdown file with Mickey Mouse listed under the CONTRIBUTORS header.
1
2
# Check out the specific remote branch
git checkout -b Mickey_Mouse_Branch
1
2
3
4
# Display the content of the file
# using PowerShell
Get-Content `
-Path CONTRIBUTING.md
Since she was told to add herself after Mickey Mouse name, she launches PowerShell and modified the file using PowerShell.
1
2
3
4
5
6
7
# Append the file with additional content
# using PowerShell
"- Minnie Mouse" | `
Out-File `
-PSPath CONTRIBUTING.md `
-Encoding utf8 `
-Append ;
After her modification, she staged the modified file and pushes the changes in the branch to the remote repository.
1
2
3
4
5
6
7
8
# Add and stage the appended file
git add CONTRIBUTING.md
# Commit the changes with a message
git commit -m "Added myself to CONTRIBUTORS list"
# Push the changes to remote branch
git push -u origin Mickey_Mouse_Branch
Next, Minnie Mouse rang Goofy and instructed him to do the same too. Goofy
checked out Mickey_Mouse_Branch
branch, added his name to the list using Bash
and created a Pull Request.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Check out the specific remote branch
git checkout -b Mickey_Mouse_Branch
# Display the content of the file
# using Bash
cat CONTRIBUTING.md
# Append the file with additional content
# using Bash
echo "- Goofy" >> CONTRIBUTING.md
# Add and stage the appended file
git add CONTRIBUTING.md
# Commit the changes with a message
git commit -m "Bashed Goofy to CONTRIBUTORS list"
# Push the changes to remote branch
git push -u origin Mickey_Mouse_Branch
Note: In order to submit a Pull Request using command line, you will need to install the Hub command line tool from GitHub.
1
2
3
# Submit a Pull Request with a message
# to GitHub
hub pull-request -m 'Updated the list and submitting PR'
Mickey Mouse got notified by an email, starts reviewing the Pull Request submitted by Goofy and found that the last commit made by Goofy is not encoded correctly in the Pull Request.
Instead of rejecting the Pull Request and inform Minnie and Goofy to do it again, Mickey has two choices to resolve the issue:
- Fetch the Pull Request to another branch and remove Goofy’s recent commit before closing the erroneous Goofy’s Pull Request
- Perform
git cherry-pick
on his commit and Minnie’s commit before closing the erroneous Goofy’s Pull Request
↑Top
Problem solving walk-through
In this section based on the scenario above, I will elaborate on the two options available for solving the problem.
↑Top
Removing recent commit in the Pull Request
If the erroneous commit is the most recent commit in the Pull Request, you can do the following by fetching the Pull Request commits to a new branch and remove the recent commit in that new branch. Once you are satisfied with it, you make a new Pull Request from that new branch that only contains the commits you wanted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Fetch the pull request to a new branch for fixing
# Syntax:
# git fetch origin pull/[Pull Request Number]/head:[New Branch Name]
git fetch origin pull/1/head:PR1
# Checkout to the branch
git checkout PR1
# Display the commits history
git log
# Reset last recent commit in the history
git reset --hard HEAD~1
# Push the fixed branch to remote
git push -u origin PR1
Submit a new Pull Request from the PR1
branch either using the site or
Hub command line developed for
GitHub.
1
2
3
# Submit a Pull Request with a message
# to GitHub
hub pull-request -m 'Removed last commit in PR1 and resubmitting PR'
↑Top
Cherry picking commits from the Pull Request
If the erroneous commit is in between multiple other working commits, you can
create a new branch and cherry-pick
those commits based on their SHA1 hash.
Once you are done with the cherry picking, you can create a new Pull Request
from the new branch and merge the Pull Request with the master
branch.
1
2
# Create a new branch for cherry picking
git checkout -b Cherries_Bucket
1
2
# List commit ids that are ahead of the branch
git log HEAD...FETCH_HEAD
Note: Commit ID is a long SHA1 hash and may be different from the example below. To
cherry-pick
, you can either input the entire SHA1 hash or the first 8 characters of the SHA1 hash.
1
2
3
4
# Pick those cherries based on the commit id
# Syntax:
# git cherry-pick [Commit Id]
git cherry-pick a481cc3c
Once you are done with picking those commits (cherries) from the Pull Request,
you can commit all those commits from this Cherries_Bucket
branch and push
them to the remote repository.
1
2
3
4
5
# Add or stage all modified files and commit the changes with a message
git commit -a -m "Cherry picked the required commits"
# Push the changes to remote branch
git push -u origin Cherries_Bucket
Submit a new Pull Request from the Cherries_Bucket
branch either using the
site or Hub command line developed
for GitHub.
1
2
3
# Submit a Pull Request with a message
# to GitHub
hub pull-request -m 'PR containing cherry picked commits'
With your Pull Request submitted, you can begin to merge from the Pull Request
1
2
3
4
5
6
7
8
# Change to local master branch
git checkout master
# Merge fast-forward changes from local source branch
git merge --no-ff Cherries_Bucket
# Push the changes to the remote master branch
git push origin master
After you have merged the Pull Request to the master
branch, you can delete
the remote and local Cherries_Bucket
branch now.
1
2
3
4
5
# Delete the remote branch
git push origin :Cherries_Bucket
# Delete the local branch
git branch -d Cherries_Bucket
↑Top
Closing outstanding Pull Request containing the erroneous commit
In order for Mickey Mouse to close the Pull Request containing the erroneous
commit that Goofy had submitted, he will need delete the remote
Mickey_Mouse_Branch
branch and the Pull Request will be marked as close.
1
2
# Delete the remote branch to close the Pull Request
git push origin :Mickey_Mouse_Branch
↑Top
Conclusions
In this blog post, you have learnt on how to use git fetch
, git reset
and
git cherry-pick
skill to save those valid commits in a Pull Request without
merging those erroneous commit to the master
branch.
All thanks to hot dog, hot dog, hot diggity dog mistakes.
If you happen to like what I am sharing, share this with others and keep them informed.
↑Top
References
- Git-SCM Docs: Git fetch
- Git-SCM Docs: Git reset
- Git-SCM Docs: Git cherry-pick
- Github Hub Manual: GitHub Hub pull-request
↑Top
Related Books
↑Top