Search code examples
gitrebaseline-endings

git rebase drops commit that only contains line-ending changes


I am trying to rebase a branch that contains a commit that fixes the line endings of some files (by making them LF instead of CRLF). If I try to do an ordinary rebase

git rebase origin/develop

I get loads of conflicting lines in a commit subsequent to the line-ending commit, because the line endings have changed, so git thinks every line has changed. But if I try instead

git rebase -s recursive -Xignore-space-at-eol origin/develop

this happens:

dropping f0eddc9f4244fb7ebdf9b3f514f875f6b34fb4b7 Fix line endings -- patch contents already upstream

How can I make git ignore line ending changes for merging purposes, but not when checking whether a patch is needed?


Solution

  • I have come up with a solution. The key is to modify the merge strategy options during the rebase. This is not officially supported, so use this technique at your own risk!

    1. Start an interactive rebase (aborting any previously-attempted rebase first).
    2. Insert a "break" line after the commit that fixes line endings in the rebase todo file.
    3. Make any other changes needed to the rebase todo file, if any, and go ahead with the rebase.
    4. When you reach the line endings fixing commit, if it has a conflict, solve the conflict by typing:
    git diff --name-only --diff-filter=U > changed-files
    xargs -a changed-files git checkout --ours --
    xargs -a changed-files dos2unix
    xargs -a changed-files git add
    rm changed-files
    git rebase --continue
    
    1. When git rebase stops immediately after the line endings commit, change the merge strategy and continue:
    echo recursive > .git/rebase-merge/strategy
    echo ' --ignore-space-at-eol' > .git/rebase-merge/strategy_opts
    git rebase --continue
    
    1. Continue the rebase as normal.