Merge conflicts are caused by working on out-dated versions of the codebase, or another developer merging a change involving similar parts of the codebase to you.
⚠️ Avoid Merge Conflicts by syncing your branch regularly Sync Guide
- Handling Conflicts
- Resolving CHANGELOG.md Conflicts Using GitHub's Web Editor
- Step-by-Step Guide to Resolve Merge Conflicts Locally
- Recovery Tips
- Helpful Resources
Changelog conflicts in CHANGELOG.md are very common in this repository because multiple pull requests frequently add new entries to the "Unreleased" section at the same time.
For these conflicts, there is a much simpler alternative to the full local rebase process: you can resolve them directly in your Pull Request on GitHub using the built-in web editor. No local setup or force push is required.
Strong Recommendation: Use the local VS Code rebase method (described below) to ensure full signing compliance. Use the web editor only if you are prepared to amend and re-sign the resolution commit locally afterward.
- The conflict is only (or primarily) in
CHANGELOG.md. - You want to keep both sets of changes — this is almost always the correct choice for changelogs, as they are designed to accumulate all entries over time.
Important: The warnings above about not blindly accepting changes apply to code files. For CHANGELOG.md, "accepting both" is safe and recommended.
-
In your PR, go to Files changed and scroll to the bottom. In the merge‑conflict banner, click Resolve conflicts to open the web editor.
-
In GitHub's web-based editor:
- Conflicted sections are highlighted (usually in red/yellow).
- You'll see Incoming change (from main) and Current change (from your branch) marked in red/highlighted areas.
-
For a changelog conflict:
- Click Accept both (if the button is available) — this combines all the bullet-point entries perfectly.
- If no "Accept both" button appears, manually remove the conflict markers (
<<<<<<< HEAD,=======,>>>>>>> your-branch) and keep all entries from both sides. - Optionally, sort or group similar entries for neatness.
-
Once all conflicts are resolved, click Mark as resolved at the top of the editor.
-
You'll see a Sign off and Commit section:
- Review your commit message
- Click Commit merge (or Commit directly to... depending on your GitHub UI).
-
Your PR will update automatically, and the conflict will be resolved.
This method is especially beginner-friendly and avoids the more advanced local rebase steps.
For more details on GitHub's web-based editor, see: The GitHub.dev web-based editor.
Example: See PR #1589 for a real example of resolving a CHANGELOG.md conflict using this method.
git checkout mybranch
git statusYou will see sections like:
<<<<<<< HEAD
code from main
=======
your branch’s code
>>>>>>> mybranch
Have a vision of what you'd like the final code to look like, given what is currently on main and what you'd like to propose.
⚠️ WARNING: Do not blindly accept both changes. This often leads to problems.⚠️ WARNING: Do not blindly accept incoming. This often leads to problems.⚠️ WARNING: Do not blindly accept existing. This often leads to problems.
Merge conflicts require:
✅ Human interpretation
Sometimes you'll be:
- Accepting both incoming and current
- Accepting only incoming
- Accepting only current
- Accepting parts of both incoming and current
Generally, you want to keep all changes that were merged to main, but additionally, layer on your changes.
✅ Resolving Conflicts Requires Human Interpretation. Merge conflicts require thinking about what the final piece should be, should it include both changes? some of each? none of one?
✅ Resolving Conflicts Requires Human Edits. Merge conflicts require manually editing the code.
Once you understand you have a merge conflict and have a vision of the the final document, we recommend using VS code.
VS Code makes solving merge-conflicts more easier with a 3-pane interface for resolving conflicts:
-> Incoming Change → code from main (left/top)
-> Current Change → code from your branch (right/top)
-> Result → the lower/third pane, where you create the final merged file.
You want to accept or reject content from the top left and top right panes, and edit the final pane in the bottom so the final code submission reasonably resolves the issue while respecting the work of others.
-> Sometimes keep Incoming (main)
-> Sometimes keep Current (your branch)
-> Often, combine both parts and edit the code manually. If the conflict is resolved correctly, VS Code will mark it as fixed.
git add .git rebase --continue7. If there are more conflicts in other files, VS Code will automatically move you to the next one. Repeat until no conflicts remain.
Once the rebase operation completes, your commits will be layered on top of main. It means your commit history will look “different” and you may even see changes to commits from other authors — this is expected, since rebase rewrites history.
If you already have an open Pull Request, you will need to update it with a force push.
Before pushing, double-check that your commits are both DCO signed and GPG verified:
git log -n 5 --pretty=format:'%h %an %G? %s'Replacing 5 with the number of commits backwards in history to check.
Ensure you see:
G = Good (valid signature)
then:
git push --force-with-leaseTip: To be safe, create a backup branch before force pushing:
git checkout -b mybranch-backupMessage: “No changes – did you forget to use git add?” → This means you resolved the conflicts but forgot to stage them. Run git add . and try again.
Message: “Are you sure you want to continue with conflicts?” → This means some conflicts are still unresolved or you did not save the files properly. Double-check your files in VS Code, make sure they are saved, and resolve any remaining conflict markers (<<<<<<<, =======, >>>>>>>).
git rebase --abortTip: At each conflict: resolve → save → stage → continue. Repeat until all conflicts are gone.
-
❌ Do not run git merge main → This creates messy merge commits. Always rebase instead.
-
❌ Do not merge into your local main → Keep main as a clean mirror of upstream/main.
-
❌ Do not open PRs from your fork’s main → Always create a feature branch for your changes.
At each conflict instance, you'll have to repeat: fix the conflict, stage the files and continue rebasing.
- Undo the last rebase commit, but keep changes staged (while still in rebase): If you are in the middle of a rebase and realize the last step went wrong, you can undo it while keeping changes staged:
git reset --soft HEAD~iNote: The number after HEAD~ refers to how many commits you want to go back.
For example:
HEAD1 → go back 1 commit
HEAD3 → go back 3 commits
HEAD~5 → go back 5 commits
Sometimes a rebase can get too messy to fix conflict by conflict. In that case, it’s often easier to start fresh:
- Abort the rebase to stop where you are:
git rebase --abort- Reset your fork's main to the upstream main and layer your commits on top of that:
git checkout main
git reset --hard upstream/main
git push origin main --force-with-lease
git checkout mybranch
git rebase upstream/main -S