Search code examples
gitgit-rebase

Need git rebase -Xignore-all-space to preserve my space


I am doing a rebase of a big change, with a lot of whitespace changes. In order for the merge to work at all, I need -Xignore-all-space.

According to git --help rebase:

ignore-space-change, ignore-all-space, ignore-space-at-eol

Treats lines with the indicated type of whitespace change as unchanged for the sake of a three-way merge. Whitespace changes mixed with other changes to a line are not ignored. See also git-diff(1) -b, -w, and --ignore-space-at-eol.

o If their version only introduces whitespace changes to a line, our version is used;

o If our version introduces whitespace changes but their version includes a substantial change, their version is used;

o Otherwise, the merge proceeds in the usual way.

However, when in a rebase, theirs and ours are swapped from their usual meaning. This means that in my rebase, all my whitespace changes are lost, since they are on their side of the merge.

How do I get git-rebase to keep my whitespace changes?


Solution

  • There's a way, but it's ugly. You're much better off keeping whitespace and "real" changes separate, and upstreaming the former first before doing the latter. But if you find yourself in this situation...

    For the sake of simplicity, I am assuming that everything is in a single commit in the current branch. This should work in a multi-commit situation, it just (again) will be more ugly. I'm also assuming the branch to rebase onto is master, and your working branch forked from it somewhere down the line.

    1. git merge master -Xignore-all-space --no-commit. Resolve the merge to your satisfaction.
    2. rm .git/MERGE_*. We're going to convince git that this is a regular commit, not a merge.
    3. git commit -a -m "Pseudo-merge from master"
    4. git rebase -i HEAD^^ and "fixup" the last change into your original one. We could have combined this with the previous step, but actually committing the pseudo-merge gives us a commit to reset to in case something goes wrong later. If this is a multiple-commit change you're working with, you may want/need to move the psuedo-merge change to a different point in the history before you squash it, to properly simulate the rebase.
    5. git rebase HEAD^ --onto master -Xtheirs The "-Xtheirs" says to always prefer their changes, but "ours" and "theirs" are flipped in a rebase, so that means to always prefer ours. This is safe, since we manually resolved the rebase (via merge) already.