KhueApps
Home/DevOps/Fixing Git 'CONFLICT (rename/modify)' and rename conflicts

Fixing Git 'CONFLICT (rename/modify)' and rename conflicts

Last updated: October 07, 2025

Overview

This guide shows practical ways to fix Git rename conflicts you may see during merges or rebases:

  • CONFLICT (rename/modify)
  • CONFLICT (rename/rename)
  • CONFLICT (rename/delete) or (delete/rename)

Key idea: resolve both the final file path and the final file content, then stage the result.

Notes on terminology:

  • ours: the current branch (HEAD) during merge
  • theirs: the branch being merged into the current branch
  • During rebase, ours/theirs semantics per commit can be counterintuitive. Use git status to verify.

Quickstart (cheat sheet)

  1. Inspect conflicts
    • git status
    • git ls-files -u (see index stages)
  2. Decide the final file path name.
  3. Merge or choose the correct file content.
  4. Remove the path you will not keep: git rm path-to-drop
  5. Stage the path you will keep: git add final-path
  6. Complete the operation: git commit (merge) or git rebase --continue (rebase)
  7. Optional: enable rerere so Git learns your resolution next time: git config --global rerere.enabled true

Minimal working example (rename/modify)

This reproduces a typical conflict and shows a clean resolution.

# Setup
mkdir -p /tmp/rename-conflict-demo && cd /tmp/rename-conflict-demo
git init
git config user.email "[email protected]"
git config user.name "You"

echo "port: 8080" > config.yaml
git add config.yaml
git commit -m "init config"
# Ensure main branch name
git branch -M main

# Branch A renames the file
git checkout -b feature-rename
mkdir -p app
git mv config.yaml app/config.yaml
git commit -m "move config to app/config.yaml"

# Main branch modifies the original path
git checkout main
echo "# added on main" >> config.yaml
git add config.yaml
git commit -m "modify config.yaml on main"

# Merge: expect CONFLICT (rename/modify)
git merge feature-rename || true

echo "--- STATUS ---"
git status --porcelain -b

Resolve by keeping the rename and carrying over the modification:

# Inspect the two versions present in the working tree
# Typically you will see both files: app/config.yaml and config.yaml

git diff --no-index app/config.yaml config.yaml || true

# Open both files and apply the changes from config.yaml into app/config.yaml.
# For this tiny example, append the comment into the renamed file:
echo "# added on main" >> app/config.yaml

# Drop the old path, keep the renamed path
git rm config.yaml
git add app/config.yaml

git commit -m "Merge feature-rename: keep rename and include main changes"

You have resolved a rename/modify conflict by choosing the final path (app/config.yaml) and merging content.

What Git is telling you

  • rename/modify: one side renamed a path; the other side modified the original path. You must decide the final name and combine content.
  • rename/rename: both sides renamed the same file (possibly to different names). Decide the final name, then merge content.
  • delete/rename: one side deleted; the other renamed. Decide whether the file survives (under the new name) or is deleted.

Step-by-step recipes

A) Fix CONFLICT (rename/modify)

Common choices:

  1. Keep the rename and include the other side’s changes
  • Compare files
    • git diff --no-index new/path old/path
  • Edit new/path to include missing changes.
  • Remove the old path: git rm old/path
  • Stage and finish: git add new/path; git commit or git rebase --continue
  1. Keep the old path, drop the rename
  • Move back: git mv new/path old/path
  • Choose content if needed
    • Take ours: git checkout --ours -- old/path
    • Take theirs: git checkout --theirs -- old/path
  • Stage and finish: git add old/path; git commit or git rebase --continue
  1. Keep both (rare)
  • Choose one as final path; save the other under a different name
    • git mv new/path chosen/path
    • git mv old/path backup/path
  • Merge content as desired, then stage and commit.

Tips:

  • mergetool can help with content merges but not with path decisions. Handle renames with git mv / git rm first.
  • To inspect base/ours/theirs blobs explicitly:
    • git ls-files -u
    • git show :1:old/path # base
    • git show :2:new/path # ours
    • git show :3:old/path # theirs

B) Fix CONFLICT (rename/rename)

  • Identify both new names: Git will show something like A renamed to B in ours and to C in theirs.
  • Choose the final name (say B):
    • If both files exist, pick one as a starting point: git mv C B or git mv B C
  • Merge content
    • git diff --no-index B C
    • Edit B to include desired changes.
  • Remove the extra path and stage
    • git rm C
    • git add B
  • Finish with commit or rebase --continue.

C) Fix CONFLICT (delete/rename)

  • Keep the rename
    • Ensure renamed file is present and correct: edit if needed
    • git add new/path
    • Finish with commit
  • Keep the deletion
    • Remove the renamed file: git rm new/path
    • Finish with commit

Strategy options that influence renames

  • Merge with content preference:

    • git merge -X ours branch # prefers ours on content conflicts
    • git merge -X theirs branch # prefers theirs on content conflicts Note: these do not automatically pick a final path for rename conflicts; verify the path result.
  • Tune rename detection sensitivity:

    • git merge -X find-renames=90% other Higher percentage requires closer similarity to count as a rename.
  • Config knobs:

    • merge.renameLimit: raise if you have many renames
    • diff.renames=true: make diffs track renames by default

Pitfalls and how to avoid them

  • Forgetting to remove the old path: results in duplicate files. Always git rm the path you are dropping.
  • Overwriting desired changes with checkout --ours/--theirs: confirm with git diff before staging.
  • Assuming mergetool resolves the path: it typically resolves content only. Use git mv/git rm for names.
  • Rebase surprises: ours/theirs semantics differ per picked commit. Rely on git status, not intuition.
  • Losing executable bits or symlink state: check git diff --staged --summary before committing.

Performance notes

  • Large rename sets can slow merges. Consider:
    • Increase merge.renameLimit temporarily.
    • Use find-renames= to tune similarity threshold.
    • Break big merges into smaller ones when possible.
    • Enable sparse-checkout to limit working tree size if unrelated paths are huge.
  • Enable rerere to auto-apply repeated resolutions in long-lived branches:
    • git config --global rerere.enabled true

Tiny FAQ

Q: Why do I see both the old and new file after merge? A: Git can leave both to let you decide the final path. Remove the one you won’t keep and stage the other.

Q: How do I pick all their changes but keep our rename? A: Apply their changes to the renamed path: edit new/path to include the diff from old/path, then git rm old/path and git add new/path.

Q: Can I automate rename conflict resolution? A: Partially. Use -X ours/theirs for content, find-renames to improve detection, and rerere to learn prior resolutions. Always verify the final path.

Q: Does rebase handle this differently than merge? A: The conflict types are the same, but ours/theirs labels are per-commit during rebase. Use git status and proceed with rebase --continue after staging the fix.

Series: Git

DevOps