Overview
“cannot merge’” class errors in Git typically mean Git refuses to create a merge commit right now. Common causes include:
- Unmerged files or an unfinished merge
- Untracked files would be overwritten
- Unrelated histories
- Fast-forward-only policy
- Protected/locked branches in CI/CD
- Out-of-date local branch or missing fetch
This guide shows quick fixes, a minimal example, and how to handle CI protections safely.
Quickstart: resolve a cannot merge’ situation
- Check status
- Run:
git statusto see conflicts, staged files, and any MERGE_HEAD state.
- If a previous merge is incomplete
- Resolve conflicts, then:
git add -A && git commit. - Or abort:
git merge --abort(if available) orgit reset --merge.
- If you have conflicts on a new merge
- Open conflicted files, edit between conflict markers, stage, and commit.
- If untracked files would be overwritten
- Move/rename those files, or
git stash -u, orgit clean -fd(destructive), then merge.
- If histories are unrelated
- First-time merge of two roots:
git merge --allow-unrelated-histories <branch>(prefer rebase or a squash if appropriate).
- If fast-forward-only is enforced
- Use an explicit merge commit:
git merge --no-ff <branch>or configure policy.
- If remote/PR is blocked by CI protections
- Update your branch:
git fetch origin && git rebase origin/main(or merge main), push, satisfy required checks, then merge via PR.
Minimal working example (conflict and resolution)
This demonstrates a common “cannot merge” due to conflicts and how to fix it.
# Start a demo repo
mkdir demo-merge && cd demo-merge
git init -b main
echo "color=blue" > config.txt
git add config.txt
git commit -m "init: config.txt blue"
# Create a feature branch and change the same line
git checkout -b feature
sed -i.bak 's/blue/green/' config.txt || perl -0777 -pe 's/blue/green/' -i config.txt
rm -f config.txt.bak
git commit -am "feat: set color to green"
# Meanwhile, simulate a conflicting change on main
git checkout main
sed -i.bak 's/blue/red/' config.txt || perl -0777 -pe 's/blue/red/' -i config.txt
rm -f config.txt.bak
git commit -am "feat: set color to red"
# Try to merge feature into main -> conflict
git merge feature || true
# You will see messages about conflicts and that merging is not possible yet.
git status
# Edit config.txt to resolve the conflict. Choose one color or a combined value.
Resolve the conflict by editing config.txt. You will see markers like:
<<<<<<< HEAD
color=red
=======
color=green
>>>>>>> feature
Pick one and remove the markers:
echo "color=green" > config.txt
git add config.txt
git commit -m "merge: resolve color conflict"
Now git merge feature has completed. If you instead wanted to abandon the merge attempt:
git merge --abort # or: git reset --merge
Common messages and what to do
| Message (excerpt) | Why it happens | Quick fix |
|---|---|---|
| Merging is not possible because you have unmerged files. | Conflicts exist and are not staged/committed. | Resolve files, git add, then git commit. |
| You have not concluded your merge (MERGE_HEAD exists). | Prior merge interrupted. | Finish with commit or git merge --abort. |
| The following untracked working tree files would be overwritten by merge: | Untracked files clash with files from the other branch. | Move them, git stash -u, or git clean -fd (destructive). |
| refusing to merge unrelated histories | Branches have different root commits. | One-time: git merge --allow-unrelated-histories <branch>; consider rebase/squash. |
| Not possible to fast-forward, aborting. | pull.ff=only set, but merge requires a merge commit. | git pull --no-ff or git merge --no-ff <branch>; adjust config if desired. |
| error: merge is not possible because you have unmerged files | Same as first row, sometimes printed differently. | Resolve conflicts then commit. |
| merge: <name> - not something we can merge | The name isn’t a valid commit/branch locally. | git fetch --all --prune; ensure the ref exists (e.g., origin/main). |
Handling CI/CD and protected branches
Many platforms enforce rules that look like “cannot merge” in pull requests:
- Required status checks: Ensure pipelines pass. Rerun or fix failing jobs.
- Up-to-date with base branch: Rebase/merge the latest
maininto your branch. - Linear history required: Rebase instead of merge, then push with
--force-with-lease. - Code owners/reviews required: Obtain approvals before merging.
- No direct pushes to protected branches: Merge via PR, not from local with
git pushto protected branches.
Typical update flow before merging a PR:
git fetch origin
# Update your feature branch atop the latest main
git checkout feature
git rebase origin/main # or: git merge origin/main
# Resolve any conflicts, then push updates
git push --force-with-lease
Pitfalls
- Using
git clean -fdwithout checking: It permanently deletes untracked files. Prefergit clean -ndto preview. - Committing conflict markers: Always remove
<<<<<<<,=======,>>>>>>>lines before committing. - Mixing rebase and merge mid-flight: Abort or finish the current operation first (
git rebase --abortorgit merge --abort). - Overusing
--allow-unrelated-histories: It can create confusing history. Use only when intentionally grafting roots. - Force-pushing without lease: Prefer
--force-with-leaseto avoid overwriting others’ work.
Performance notes
- Large repos: Reduce working set before merges with sparse-checkout.
- Speed up status/merge detection: Enable fsmonitor if supported.
- Fetch smartly:
git fetch --prune --filter=blob:nonefor partial clones (server support required) to make updating before merges faster. - Avoid repeated full clones in CI: Cache the repository or use
--reference/partial clone to reduce I/O. - Minimize merge computations: Keep branches short-lived and rebase frequently to reduce conflict surfaces.
Diagnostics checklist
git statusshows unmerged files? Resolve, add, commit.- Is
MERGE_HEADpresent? Finish or abort the merge. - Untracked-overwrite warning? Stash/move/clean the files.
- Different roots? Decide if unrelated histories should be merged.
- Fast-forward-only set? Use
--no-ffor change policy. - Remote rejects merge? Update branch, pass checks, and respect protections.
Tiny FAQ
Q: Git says “cannot merge” but there are no conflicts. Why? A: You might be mid-merge (MERGE_HEAD set), on a protected branch, or fast-forward-only is enforced. Check git status and your repo/policy settings.
Q: Should I use rebase or merge to get up-to-date before merging? A: Follow your team policy. Rebase keeps a linear history; merge preserves branch structure. Both resolve “out-of-date branch” blockers.
Q: I get “unrelated histories.” Is it safe to allow? A: Only if you truly want to combine separate roots (e.g., importing a repo). Otherwise, prefer a fresh branch off the desired base and cherry-pick.
Q: What’s the safest way to recover from a bad merge? A: If unpushed, git reset --hard <pre-merge-commit>. If pushed, revert the merge with git revert -m 1 <merge-commit> to preserve history.