Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)?

like image 702
Matthew Strawbridge Avatar asked Nov 01 '22 23:11

Matthew Strawbridge


1 Answers

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.

like image 130
onionjake Avatar answered Nov 15 '22 04:11

onionjake