Table of Contents
Introduction to git cherry-pick
Cherry-picking in Git refers to the process of selecting a commit from one branch and applying it onto another branch. This action does not merge the whole branch from which the commit is taken; instead, it selectively takes one or a range of commits from a branch and applies it onto another. This is done using the git cherry-pick command.
In this tutorial, we will look at the steps to apply
cherry-picking in git. Also, we are going to cover the different methods of using
cherry-pick in git with examples.
git cherry pick syntax
Following is the syntax of of git cherry-pick with all the list of supported options:
git cherry-pick [options] <commit-hash>
<commit-hash> is the hash identifier of the commit you wish to cherry-pick.
git cherry-pickcommand, it's essential to create a temporary branch from the target branch, not the source branch. This ensures that cherry-picked changes are tested and validated in the exact context they will eventually be merged into. Creating the temporary branch from the source branch may lead to testing in a different environment, potentially resulting in unforeseen issues or conflicts once merged into the intended target. Always prioritize the integrity and context of your target branch when cherry-picking to ensure smooth integration of changes.
git cherry-pick workflow
Cherry-picking a Single Commit
You've got a production bug report. The bug was already fixed in the '
feature-xyz' branch as part of another task, but '
feature-xyz' isn't ready to be merged into production yet. You decide to cherry-pick just the bug-fix commit without waiting for the entire feature to be completed.
Following is the general workflow of performing git cherry-pick:
# Starting from a primary branch (e.g., main or master): git checkout main # 1. Fetch the Latest Commits from Remote: git fetch origin # 2. Identify the Commit: # Navigate to the 'feature-xyz' branch: git checkout feature-xyz # Use git log to identify the commit hash of the bug fix: git log # (Note the commit hash e.g., d4f3e5b) # 3. Create a Temporary Branch from Production: git checkout production git checkout -b hotfix-cherry-pick # 4. Cherry-pick the Commit onto the Temporary Branch: git cherry-pick d4f3e5b # 5. Resolve Any Conflicts: # If there are merge conflicts, manually resolve them. # After resolving conflicts, stage the changes: git add . # Continue the cherry-pick process: git cherry-pick --continue # 6. Push the Changes to the Temporary Branch on Remote (Optional but recommended): git push origin hotfix-cherry-pick # 7. Test the Changes on the Temporary Branch: # This can be locally or on any staging environment you might have. # 8. Merge the Temporary Branch into Production: git checkout production git merge hotfix-cherry-pick # 9. Push the Changes to the Remote Repository: git push origin production # 10. Cleanup: # If everything is stable, you can delete the temporary branch locally and remotely. git branch -d hotfix-cherry-pick git push origin --delete hotfix-cherry-pick # 11. Communicate: # Inform your team about the cherry-picked commit and the merge into production.
Cherry-picking Multiple Commits
You've received multiple bug reports related to
production. These bugs were already addressed in the
feature-xyz branch over a series of commits. The
feature-xyz branch isn't ready for a complete merge into
production, so you decide to cherry-pick only the bug-fix commits.
# Starting from a primary branch (e.g., main or master) to fetch the latest changes: git checkout main git fetch origin # 1. Identify the Commits: # Navigate to the 'feature-xyz' branch: git checkout feature-xyz # Use git log to identify the commit hashes of the bug fixes: git log # Note down the relevant commit hashes (e.g., a7c8e2f, b9d0e3g, c1f2h3i). # 2. Create a Temporary Branch from Production: git checkout production git checkout -b hotfix-multi-cherry-pick # 3. Cherry-pick the Multiple Commits onto the Temporary Branch: git cherry-pick a7c8e2f b9d0e3g c1f2h3i # 4. Resolve Any Conflicts: # If there are merge conflicts, manually resolve them for each commit. # After resolving conflicts for a commit, stage the changes and continue: git add . git cherry-pick --continue # Repeat the above two steps for each conflicting commit. # 5. Push the Changes to the Temporary Branch on Remote (Optional but recommended): git push origin hotfix-multi-cherry-pick # 6. Test the Changes on the Temporary Branch: # Before merging, test thoroughly to ensure no issues were introduced. # 7. Merge the Temporary Branch into Production: git checkout production git merge hotfix-multi-cherry-pick # 8. Push the Changes to Production on the Remote Repository: git push origin production # 9. Cleanup: git branch -d hotfix-multi-cherry-pick git push origin --delete hotfix-multi-cherry-pick # 10. Communicate: # Inform the team about the cherry-picked commits and the merge into production.
Advanced Use Cases
Cherry-picking a Sequence of Commits (range)
When you have a sequence of consecutive commits that you'd like to cherry-pick, you can use a commit range. This can be especially handy when you've made a series of related changes across multiple commits, and you want to bring all of those changes into another branch without cherry-picking each commit individually.
# Starting from a primary branch (e.g., main or master) to fetch the latest changes: git checkout main git fetch origin # 1. Identify the Sequence of Commits: # Navigate to the branch that has the sequence of commits you want to cherry-pick: git checkout source-branch # Use git log to review the commits and note the range you want to cherry-pick: git log # Suppose you want to cherry-pick commits from a7c8e2f up to (and including) d4f3e5b. # 2. Navigate to the Target Branch: git checkout target-branch # 3. Cherry-pick the Sequence of Commits: git cherry-pick a7c8e2f^..d4f3e5b # 4. Resolve Any Conflicts: # If there are merge conflicts, resolve them for each commit in the sequence. # After resolving conflicts for a commit, stage the changes and continue: git add . git cherry-pick --continue # Repeat the resolution process for each conflicting commit in the sequence. # 5. Test the Changes: # Ensure the sequence of commits didn't introduce any issues. # 6. Push the Changes to the Remote Repository: git push origin target-branch
- The caret (^) in
a7c8e2f^is crucial. Without it, the start commit would be excluded from the cherry-pick. Including the caret ensures that the start commit is included.
- It's essential to be cautious when cherry-picking a sequence of commits. Ensure that the order and context of the commits still make sense in the target branch.
- As with any cherry-pick operation, be prepared for potential merge conflicts, especially when cherry-picking multiple commits. Remember that each commit in the sequence might introduce its own set of conflicts.
Editing a Commit During Cherry-pick
Sometimes, while cherry-picking a commit, you might realize that you need to make minor adjustments to the changes or the commit message to better fit the context of the target branch. Instead of cherry-picking and then amending the commit in two separate steps, Git offers an option to edit the commit during the cherry-pick itself.
# Starting from a primary branch (e.g., main or master) to fetch the latest changes: git checkout main git fetch origin # 1. Navigate to the Target Branch: git checkout target-branch # 2. Start the Cherry-pick with the Edit Option: git cherry-pick -e <commit-hash> # This will initiate the cherry-pick and pause, allowing you to modify the commit message. # If you need to edit the content of the commit (the actual changes) rather than just the commit message, make your desired changes now. # 3. Stage Any Changes (if you modified content): git add . # 4. Finalize the Commit: git cherry-pick --continue # At this point, if you've only edited the commit message, it will finalize the cherry-pick with the new message. If you made changes to the content, the commit will include those changes as well. # 5. Test the Changes: # Ensure the edited commit behaves as expected in the target branch. # 6. Push the Changes to the Remote Repository: git push origin target-branch
--editoption is primarily meant to allow editing the commit message. However, while the cherry-pick process is paused, you can also make changes to the commit's content. This can be useful if you need to make minor adjustments that are specific to the context of the target branch.
- Always be cautious when editing commits, especially if making changes to the content. Ensure the modified commit still accurately represents its intended purpose and doesn't introduce unexpected behavior.
- Remember that even with the edit option, you might still encounter merge conflicts. Be prepared to resolve them as you would during a standard cherry-pick operation.
Viewing Changes Before Cherry-picking
Before committing to a cherry-pick, you might want to get a full picture of what's in the commit, especially if it comes from another collaborator or if it's been a while since the commit was made.
# Starting from any branch: git fetch origin # 1. Review the Commit Log (Optional but recommended): # This step can help you identify and note down the hash of the commit you're interested in. git log --oneline # 2. View the Changes of a Specific Commit: git show <commit-hash> # This command will provide a diff view of the changes introduced by the commit. You'll be able to see added/removed lines, file changes, and the commit message.
git showby default uses the "patch" format, which displays the content changes and metadata for the commit. You'll see color-coded additions (in green) and deletions (in red).
- If you want a more summarized view, you can combine
git showwith various flags. For instance,
git show --stat <commit-hash>provides a summary of the changed files and the number of insertions and deletions.
- To view changes for a commit on a remote branch that hasn't been merged locally, first fetch the changes using git fetch origin, then use the git show command with the remote branch and commit hash: git show origin/remote-branch-name:<commit-hash>.
- Remember that reviewing changes in a commit is a proactive step that can save time and prevent potential issues. It can help you identify if the commit contains more changes than you anticipated or if it might conflict with the current state of your target branch.
Abort Cherry-pick Process
If, during the cherry-picking process, you decide not to continue (especially after encountering conflicts or other issues), you can abort the process to restore your branch to its previous state.
# If you're in the middle of a cherry-pick and decide to abort: git cherry-pick --abort
git cherry-pick --abortwill cancel the cherry-pick operation and return your branch to its original state, undoing any changes made by the cherry-pick.
- If you had already resolved some merge conflicts and decided to abort afterward, those resolved changes would also be discarded, and your branch would return to the state before the cherry-pick started.
- It's important to remember that if you've already completed the cherry-pick (i.e., the cherry-picked commit is finalized and there's no ongoing cherry-pick operation), then you can't use
git cherry-pick --abortto undo it. In that case, you'd need to use another method, like git reset or git revert, to undo the commit.
- Always use the
--abortcommand with caution and ensure you truly want to discard the ongoing operation. It's a powerful command that can undo your recent actions related to the cherry-pick.
Best Practices and Considerations
- Understand the Commit: Before cherry-picking, always understand the context and contents of a commit. Ensure that the changes in the commit make sense in the branch you're cherry-picking to. It's beneficial to use
git showto review the changes of a commit before cherry-picking.
- Avoid Overusing Cherry-pick: While cherry-picking is powerful, overusing it can lead to a cluttered and confusing git history. Whenever possible, use merging or rebasing for larger sets of changes.
- Test After Cherry-picking: Always test the changes after cherry-picking to ensure that they work correctly in the new branch's context. Remember, the commit was initially tested in a different branch's environment.
- Resolve Conflicts Carefully: Conflicts are common during cherry-picking, especially if the source and target branches have diverged significantly. Take your time to understand and resolve these conflicts properly.
- Document Cherry-picked Commits: When cherry-picking, the new commit will have a different hash. It can be useful to add a note in the commit message indicating the original commit hash. This provides traceability.
- Beware of Duplicate Changes: If a branch with a cherry-picked commit gets merged back into the original branch, it could lead to duplicate commits (since git sees them as different commits due to different hashes) or merge conflicts. Always be aware of the downstream and upstream effects of cherry-picking.
- Avoid Cherry-picking from Future: It's generally risky to cherry-pick from a "future" branch (like a development branch) back to a "past" branch (like a production branch). Doing so might introduce dependencies or changes that the past branch is not ready for.
cherry-pick command allows developers to select and apply specific commits from one branch to another. While it offers precise control over commit selection, it's essential to use it judiciously. Proper understanding of the commit context, conflict resolution, and post-operation testing are crucial to ensure smooth integration of changes. Over-reliance on cherry-picking can lead to a convoluted git history. Best practices such as atomic commits, thorough testing post-cherry-picking, careful conflict resolution, and communication within teams can enhance the efficiency and clarity of cherry-picking operations.