KhueApps
Home/DevOps/Fixing “You have unmerged files” after Git merge or rebase

Fixing “You have unmerged files” after Git merge or rebase

Last updated: October 07, 2025

Overview

When Git says “error: You have unmerged files,” a merge or rebase created conflicts that must be resolved before Git can proceed. The fix is always: inspect conflicts, choose the correct content per file, stage the resolutions, then complete or abort the operation.

Quickstart (90 seconds)

  1. See what’s conflicted:
    • git status
    • git ls-files -u # detailed unmerged entries
  2. Open each conflicted file, resolve the <<<<<<<, =======, >>>>>>> markers.
  3. For each resolved file: git add <file>
  4. If you were merging: git commit
  5. If you were rebasing: git rebase --continue
  6. If you want to bail out:
    • Merge: git merge --abort
    • Rebase: git rebase --abort

Symptoms

  • During merge: error: You have unmerged files; fix conflicts and then commit the result.
  • During rebase: error: could not apply <commit>; resolve all conflicts manually, mark them as resolved with "git add <file>" and run "git rebase --continue".
  • git status shows “both modified,” “both added,” “deleted by them/us,” or rename conflicts.

Why it happens

  • Two branches changed the same lines or file operations (modify/rename/delete) in incompatible ways.
  • Rebase replays commits atop a new base; conflicts arise where history diverges.

Minimal working example

This creates a conflict and resolves it both for merge and rebase.

# Start clean
mkdir demo-merge-rebase && cd demo-merge-rebase
git init -b main

echo "v1" > app.txt
git add app.txt && git commit -m "init app.txt v1"

# Branch and change the same line
git checkout -b feature
printf "v2-feature\n" > app.txt
git commit -am "feature: change app.txt"

git checkout main
printf "v2-main\n" > app.txt
git commit -am "main: change app.txt"

# 1) Merge path (conflict)
git merge feature || true   # expect conflict
# Inspect
git status

# Resolve by choosing main’s version (ours) or feature’s (theirs)
# Option A: keep main version
git checkout --ours app.txt
# Option B: keep feature version (comment Option A and uncomment next line)
# git checkout --theirs app.txt

git add app.txt
git commit -m "merge: resolve conflict in app.txt"

# Reset repo to show rebase path
cd ..; rm -rf demo-merge-rebase
mkdir demo-merge-rebase && cd demo-merge-rebase
git init -b main

echo "v1" > app.txt
git add app.txt && git commit -m "init app.txt v1"

git checkout -b feature
printf "v2-feature\n" > app.txt
git commit -am "feature: change app.txt"

git checkout main
printf "v2-main\n" > app.txt
git commit -am "main: change app.txt"

# 2) Rebase path (conflict)
git checkout feature
git rebase main || true     # expect conflict

# Resolve, then continue
git checkout --theirs app.txt   # or --ours
git add app.txt
git rebase --continue

Example conflict markers you might see inside a file:

<<<<<<< HEAD
v2-main
=======
v2-feature
>>>>>>> feature

Edit the file to the intended content (remove the markers), then stage and continue.

Standard resolution workflow

  1. Identify conflicts
    • git status
    • git diff --name-only --diff-filter=U
    • git ls-files -u
  2. Decide per file
    • Keep one side entirely: git checkout --ours <path> or git checkout --theirs <path>
    • Or merge manually: edit, remove markers, ensure code compiles/tests pass.
  3. Stage resolutions
    • git add <path> for resolved files
    • git rm <path> if you intentionally delete
  4. Complete the operation
    • Merge: git commit
    • Rebase: git rebase --continue
  5. Abort if needed
    • Merge: git merge --abort
    • Rebase: git rebase --abort

Tip: Prefer resolving file-by-file rather than git add -A to avoid accidental staging.

Handling common conflict types

  • Both modified (same file): edit or choose ours/theirs, then git add.
  • Delete/modify:
    • Keep deletion: git rm <file>
    • Keep modification: git checkout --theirs <file> (or --ours) && git add <file>
  • Both added (same path): rename one file or combine contents, then git add.
  • Rename/rename: choose the final name, git mv as needed, resolve contents, git add.
  • Binary file conflict: choose one side entirely: git checkout --ours <bin> or --theirs <bin>; then git add.

Rebase-specific notes

  • To skip the problematic commit (rarely recommended): git rebase --skip
  • View rebase todo: git rebase --edit-todo
  • If you’re unsure, abort safely: git rebase --abort

Useful configuration

# Show base context in conflicts (helps manual merges)
git config --global merge.conflictStyle diff3

# Remember and auto-apply past resolutions
git config --global rerere.enabled true

# Prefer rebase on pull for linear history (optional)
git config --global pull.rebase true

Pitfalls and how to avoid them

  • Using reset or checkout to discard without thinking
    • git reset --hard will drop uncommitted work. Only use when you’re certain.
  • Staging unresolved markers
    • Always search for <<<<<<< and >>>>>>> after editing.
  • Accidental mass “theirs”/“ours”
    • Review changes with git diff before git add.
  • Conflicts hidden by CRLF differences
    • Set consistent line endings: git config core.autocrlf input (or true on Windows) and use .gitattributes.
  • Submodule conflicts
    • Resolve by checking out the desired submodule commit, then git add <submodule-path>.

Performance notes (large repos/monorepos)

  • Limit scope while resolving
    • Use git status -uno to skip untracked scanning.
    • Resolve a subset: git add <dir>/ to stage directory-by-directory.
  • Sparse checkout for focused work
    • git sparse-checkout init --cone && git sparse-checkout set <dirs>
  • Speed up repeated merges
    • Enable rerere to auto-apply known resolutions.
  • Avoid expensive tools on each file change
    • Temporarily disable heavy pre-commit hooks; re-enable after merge.

Verification checklist

  • git status shows no unmerged paths.
  • Tests build/run successfully.
  • For rebase, log is linear and expected: git log --oneline --graph --decorate.
  • No leftover conflict markers: git grep -nE '^(<<<<<<<|=======|>>>>>>>)' || true

Tiny FAQ

  • Q: Can I resolve everything by taking one side globally?

    • A: Sometimes. For merge: git checkout --theirs . (or --ours .) then review diffs, run tests, commit. Use with caution.
  • Q: I resolved conflicts but Git still complains.

    • A: Ensure all conflicted paths are staged (git add). Check with git diff --name-only --diff-filter=U.
  • Q: How do I see which commits caused the conflict during rebase?

    • A: git status shows the commit; use git log -p --merge or review the commit in the rebase todo.
  • Q: Can I use a GUI merge tool?

    • A: Yes. Configure one (e.g., meld, kdiff3) via git mergetool; it will mark resolved files for you.
  • Q: Is --ours/--theirs inverted during rebase?

    • A: During merge, ours = current branch, theirs = merging branch. During rebase, ours = the rebased commit, theirs = the upstream/base you’re rebasing onto.

Series: Git

DevOps