KhueApps
Home/DevOps/Troubleshooting Git cannot merge' in local and CI workflows

Troubleshooting Git cannot merge' in local and CI workflows

Last updated: October 07, 2025

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

  1. Check status
  • Run: git status to see conflicts, staged files, and any MERGE_HEAD state.
  1. If a previous merge is incomplete
  • Resolve conflicts, then: git add -A && git commit.
  • Or abort: git merge --abort (if available) or git reset --merge.
  1. If you have conflicts on a new merge
  • Open conflicted files, edit between conflict markers, stage, and commit.
  1. If untracked files would be overwritten
  • Move/rename those files, or git stash -u, or git clean -fd (destructive), then merge.
  1. If histories are unrelated
  • First-time merge of two roots: git merge --allow-unrelated-histories <branch> (prefer rebase or a squash if appropriate).
  1. If fast-forward-only is enforced
  • Use an explicit merge commit: git merge --no-ff <branch> or configure policy.
  1. 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 happensQuick 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 historiesBranches 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 filesSame as first row, sometimes printed differently.Resolve conflicts then commit.
merge: <name> - not something we can mergeThe 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 main into 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 push to 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 -fd without checking: It permanently deletes untracked files. Prefer git clean -nd to preview.
  • Committing conflict markers: Always remove <<<<<<<, =======, >>>>>>> lines before committing.
  • Mixing rebase and merge mid-flight: Abort or finish the current operation first (git rebase --abort or git merge --abort).
  • Overusing --allow-unrelated-histories: It can create confusing history. Use only when intentionally grafting roots.
  • Force-pushing without lease: Prefer --force-with-lease to 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:none for 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 status shows unmerged files? Resolve, add, commit.
  • Is MERGE_HEAD present? 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-ff or 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.

Series: Git

DevOps