Matthew Strawbridge
Matthew Strawbridge

Reputation: 20620

Git rename detection of empty file

I recently hit a problem where an empty file was renamed differently in two branches but merged without a conflict being raised.

Steps to recreate are as follows.

  1. Create an empty file.

    git init
    touch empty
    git add empty
    git commit -m "add empty file"
    
  2. Rename it in the branch.

    git checkout -b branch
    git mv empty empty-in-branch
    git commit -m "empty -> empty-in-branch"
    
  3. Rename it differently in the master.

    git checkout master
    git mv empty empty-in-master
    git commit -m "empty -> empty-in-master"
    
  4. Merge branch into master.

    git merge --no-commit branch
    

This gives the message Automatic merge went well; stopped before committing as requested.

git status shows just the new file empty-in-branch. But there is no deletion of empty-in-master so if we commit at this stage we'll get both files.

I'd expect this to be flagged as a merge conflict that needed manual resolution (i.e. deciding which empty file to keep). That's what happens if the original file is non-empty.

Is there something special about empty files that affects the rename detection? Are there any parameters I could add to the git merge that will get it to detect the conflict (e.g. tweaking the merge strategy)?

Upvotes: 5

Views: 650

Answers (1)

onionjake
onionjake

Reputation: 4035

Empty files are no longer considered for renames on a recursive merge as of this commit: https://github.com/git/git/commit/4f7cb99ada26be5d86402a6e060f3ee16a672f16

Older versions of Git still report it as a conflict.

$ git --version
git version 1.7.9.5
# ... follow OP instructions to reproduce
$ git merge --no-commit branch
CONFLICT (rename/rename): Rename "empty"->"empty-in-master" in branch "HEAD" rename "empty"->"empty-in-branch" in "branch"
Automatic merge failed; fix conflicts and then commit the result.
$ git status
# On branch master
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both deleted:       empty
#   added by them:      empty-in-branch
#   added by us:        empty-in-master
#
no changes added to commit (use "git add" and/or "git commit -a")

Git doesn't implicitly track renames, so without the rename detection what ends up happening is Git just sees that both commits deleted the file empty, and that each commit added a new file.

There is an option to change this behavior for git-diff (https://github.com/git/git/commit/90d43b07687fdc51d1f2fc14948df538dc45584b), but currently it is not exposed in an option to git merge.

The other merge strategies do not seem to give the desired behavior either.

Upvotes: 2

Related Questions