How to merge a hotfix branch into a feature branch in Git without creating duplicate commits?
I’m working with Git and have the following workflow:
- Created repository:
mkdir GitTest2
cd GitTest2
git init
- Made initial commits to master:
echo "On Master" > file
git commit -a -m "Initial commit"
- Created feature1 branch and did some work:
git branch feature1
git checkout feature1
echo "Feature1" > featureFile
git commit -a -m "Commit for feature1"
- Discovered a bug in master, created hotfix branch:
git checkout master git branch hotfix1 git checkout hotfix1
- Fixed the bug in hotfix branch and merged back to master:
echo "Bugfix" > bugfixFile
git commit -a -m "Bugfix Commit"
git checkout master
git merge --no-ff hotfix1
- Continued development on feature1:
git checkout feature1
Now I need to apply the hotfix to my feature branch because the bug also affects it. How can I achieve this without duplicating commits into my feature branch?
I want to avoid creating two new commits on my feature branch that have no relation to the feature implementation. This is especially important when using pull requests, as these commits would be included in the PR and require review even though they’ve already been reviewed as part of the hotfix.
I tried git merge master --ff-only but got “fatal: Not possible to fast-forward, aborting.” I’m not sure if this would have helped anyway.
What’s the best approach to merge a hotfix into a feature branch in this scenario?
To merge a hotfix branch into a feature branch in Git without creating duplicate commits, you have several effective approaches. The key is to integrate the hotfix changes cleanly while maintaining a clean commit history that doesn’t include unrelated commits in your feature branch pull requests.
The most common solutions are cherry-picking specific commits, merging with proper flags, or rebasing your feature branch. Each approach has different implications for your commit history and workflow.
Contents
- Understanding the Problem
- Cherry-Pick Approach: Recommended Method
- Merge Approach: Direct Integration
- Rebase Approach: Rewriting History
- Comparison of Approaches
- Best Practices for Hotfix Integration
- Conclusion
Understanding the Problem
When you merge master (which now contains the hotfix) into feature1, Git will typically create a merge commit that includes the entire history from master up to the hotfix. This means not only will your hotfix be applied, but potentially other commits from master that don’t belong in your feature branch.
The issue you encountered with git merge master --ff-only failed because feature1 and master have diverged - feature1 doesn’t contain the hotfix commit, and master doesn’t contain the feature1 changes. A fast-forward merge isn’t possible in this scenario.
As the Atlassian Git tutorial explains, cherry-picking allows you to apply specific changes without merging entire branches, which is exactly what you need in this situation.
Cherry-Pick Approach: Recommended Method
The cherry-pick approach is generally the cleanest method for applying hotfixes to feature branches without duplicating commits.
Step-by-step process:
- Identify the hotfix commit(s):
git log master --oneline --grep="Bugfix"
- Switch to your feature branch:
git checkout feature1
- Cherry-pick the specific hotfix commit:
git cherry-pick <commit-hash>
Example with your scenario:
git checkout feature1 git cherry-pick BugfixCommitHash
Benefits of cherry-picking:
- Only applies the specific fix you need
- Creates a new commit on feature1 that’s clearly related to the hotfix
- Doesn’t pull in unrelated commits from master
- Maintains separation of concerns
As Nick Janetakis explains, “It applies the change by creating a new commit for each ‘copied’ commit, you’ll end up with the same 2 commit details in each branch but the ‘copied’ commit will have a different git commit SHA.”
Handling conflicts:
If conflicts occur during cherry-pick:
git cherry-pick --abort # if you want to cancel
git cherry-pick --continue # after resolving conflicts
Merge Approach: Direct Integration
While cherry-pick is often preferred, you can also use merge with specific strategies to control how commits are integrated.
Basic merge approach:
git checkout feature1 git merge hotfix1
Using merge strategies:
- Recursive strategy with ours/their option:
git checkout feature1 git merge -s recursive -X theirs hotfix1
- Using octopus for multiple branches:
git checkout feature1 git merge --no-ff hotfix1
As mentioned in the Stack Overflow discussion, when you try to merge one branch with another, Git can simplify things by moving the pointer forward if there’s no divergent work to merge together.
Potential issues with merge:
- May create a merge commit that includes unrelated history
- Can make the feature branch history more complex
- May pull in commits from master that don’t belong in feature1
Rebase Approach: Rewriting History
Rebasing can also be an effective approach, though it rewrites history which may not be suitable for all workflows.
Rebase feature branch onto master:
git checkout feature1 git rebase master
How this works:
- Git takes all commits from feature1 that aren’t in master
- Temporarily removes them
- Applies them on top of master (which includes the hotfix)
- Re-applies the feature1 commits
As the Git documentation explains, “when you try to merge one commit with a commit that can be reached by following the first commit’s history, Git simplifies things by moving the pointer forward because there is no divergent work to merge together — this is called a ‘fast-forward.’”
Benefits of rebase:
- Results in a linear history
- Automatically incorporates the hotfix
- No extra merge commits
Caveats:
- Rewrites history (should not be used on shared branches)
- Can cause conflicts that need resolution
- Changes commit hashes
Comparison of Approaches
| Approach | History Impact | Complexity | Conflict Handling | Best For |
|---|---|---|---|---|
| Cherry-pick | Minimal (only specific commits) | Low | Manual per commit | Targeted hotfix application |
| Merge | Adds merge commit | Low | Automatic merge | Simple integration |
| Rebase | Rewrites history | High | Interactive | Linear history preference |
When to use each:
- Cherry-pick: Best when you only want specific commits and want to keep feature branch history clean
- Merge: Best when you want to preserve branch history and don’t mind merge commits
- Rebase: Best when you want a linear history and can rewrite shared branch history
As discussed in the GitLab documentation, “Repeat for each branch that needs the contents of commit abc123f. If the code you need was added over the course of multiple commits, cherry-pick each of those commits into your desired target branch.”
Best Practices for Hotfix Integration
1. Create hotfixes from the correct base:
- Hotfixes should typically be based on the production branch (master)
- Avoid creating hotfixes from development branches
2. Keep hotfix focused:
- Each hotfix should address a single issue
- Don’t combine multiple fixes in one hotfix
3. Document the integration:
- Use clear commit messages that reference the hotfix
- Consider adding
[hotfix]prefix to feature branch commits
4. Test after integration:
- Always verify that the hotfix works in the feature branch context
- Run tests to ensure the fix doesn’t break existing functionality
5. Communicate with your team:
- Let team members know when hotfixes are applied to feature branches
- Update any relevant documentation or tickets
As mentioned in the Linux Hint guide, “Create and switch to the ‘hotfix’ branch, perform the needed task and commit changes to the repository. Execute the ‘$ git merge –no-ff
Conclusion
For your specific scenario, I recommend using cherry-pick as the primary method to integrate the hotfix into your feature branch:
git checkout feature1 git cherry-pick BugfixCommitHash
This approach will:
- Apply only the specific bug fix to your feature branch
- Create a clean, isolated commit for the hotfix in feature1
- Avoid duplicating the entire master history
- Keep your pull request focused on feature-related changes
If you need to apply multiple commits from the hotfix, cherry-pick each one individually. For more complex scenarios or when you prefer a linear history, consider rebasing your feature branch onto master.
Remember that the best approach depends on your team’s workflow, branching strategy, and how you manage code reviews. Choose the method that makes the most sense for your project’s specific needs and maintain clear communication about hotfix integrations to avoid confusion during code reviews.