Search code examples
gitgit-mergegit-rebase

Rename detection makes `git rebase` remove a random file


I have a script that among other things uses git rebase to remove a specific commit from the current branch.

In one case, it removes a seemingly random file. After long debugging session, I've managed to track it down to a rename detection mechanism during a merge performed by git rebase.

All my attempts to disable this mechanism failed. What can I do?

Here is a shell script that reproduces the problem:

#!/bin/sh

mkdir test-repo
cd test-repo

git init
git config --local user.name nobody  # just in case
git config --local user.email whatever@myself.lan  # just in case

printf 'x\nx\n' >foo
git add .
git commit -m 'Added some files'

rm foo
printf 'y\nx\n' >bar  # the contents of bar are slightly similar to foo
git add .
git commit -m 'The comit to discard'

printf 'z\nx\n' >bar
git add .
git commit -m 'The commit to keep'

git rebase --strategy-option=theirs --onto HEAD~2 HEAD~1
if [ ! -f bar ]
then
    echo 'WHY!?'
fi

Solution

  • It looks like the modern merge strategy called ort does not implement merge.renames=false and always does rename detection.

    You can select the old merge strategy recursive that does heed this setting:

    git -c merge.renames=false rebase --strategy=recursive --onto HEAD~2 HEAD~1
    

    Be warned, though, that this will leave behind a conflict that cannot be resolved automatically. In particular, --strategy-option=theirs does not do anything useful. You can then

    git checkout --theirs bar
    

    to resolve the conflict but is that really what you need, because then you have both foo and bar in the repository?