I know removing trailing whitespace can be done with a pre-commit hook. I am interested in doing it manually. I read the question here:
Make git automatically remove trailing whitespace before committing - Stack Overflow
The answer closest to what I want is the "automatic version" from ntc2:
(export VISUAL=: && git -c apply.whitespace=fix add -ue .) && git checkout . && git reset
That command works well except it seems to be only for changes on files that are already in the repo, not new files. I have a bunch of files that are new, meaning they aren't yet in the repo. I want to remove whitespace from those files so I tried add -A instead of -u but that didn't make a difference.
To manually clean up whitespace from your last 3 commits, you can do this:
git rebase --whitespace=fix HEAD~3
When I work on a topic branch, I track the upstream branch (usually by creating it like this)
git checkout -b topic -t
Which allows me to drop the last argument from git rebase
. So once I'm done & ready to merge, I can clean the whole topic branch quickly with:
git ws
# aliased to rebase --whitespace=fix
Note that, unlike the HEAD~3 example, this will actually rebase your changes upon the upstream branch if it's changed! (But that's also what I want, in my workflow.)
I like Luke's answer, except for the limitation that you need to either manually specify the base commit, or use a rebase-style workflow, where your history is linearized. I propose a modification that doesn't need an extra argument and doesn't change the topology of your commit graph. As a shell command:
git rebase --whitespace=fix --onto $(git merge-base HEAD @{u})
Or as a ~/.gitconfig alias:
ws = "!git rebase --whitespace=fix --onto $(git merge-base HEAD @{u})"
I prefer this because sometimes I want to rebase my changes, but if I think think there might be a merge conflict I prefer to merge, so that both my original change and the conflict resolution will be recorded in the history. That way I can later second-guess the conflict resolution and redo it if necessary.
Given that I don't always rebase, I prefer not to mix whitespace-fixing with rebasing; hence this modification to Luke's answer.
In addition, I enable the default pre-commit hook which aborts on whitespace errors:
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
This gives the following workflow, which I like because it's manual enough that I know what's going on but automated enough not to get in the way:
- hack hack hack, introduce whitespace error
- attempt to commit
- commit fails with whitespace error due to pre-commit hook
git commit --no-verify
to commit anyway
git ws
use the alias to fix
Note on the usage of --onto
: It's not necessary here, but I find it easier to reason about how the rebase works this way. In Luke's version, HEAD~3
is the <upstream>
in the man page, while in my version <upstream>
keeps its default value of the real upstream of the branch. You wind up with the same result either way though.
Simple fix
The command you quoted
(export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .) && git checkout . && git reset
works if you first add the files you want to fix with git add -N <files you want to fix>
. The add -N
essentially tells Git to pretend you'd previously committed empty versions of the files.
Error you got
I don't understand why you get fatal: Empty patch. Aborted.
error with add -Ae
, but it looks like a bug, since doing plain git add -A . && git diff --cached
shows that the patch should not actually be empty.
Better whitespace fixer
I recently updated
my answer that you linked to
with a better Git alias for fixing whitespace. Here's a rewrite of that alias
using
Luke's rebase trick and
a less redundant control flow:
fixws =!"\
if (! git diff-index --quiet --cached HEAD); then \
\
git diff-files --quiet `git rev-parse --show-toplevel` ; \
export NEED_TO_STASH=$? ; \
\
git commit -m FIXWS_SAVE_INDEX && \
if [ 1 = $NEED_TO_STASH ] ; then git stash save FIXWS_SAVE_TREE; fi && \
git rebase --whitespace=fix HEAD~ && \
git reset --soft HEAD~ && \
if [ 1 = $NEED_TO_STASH ] ; then git stash pop; fi ; \
fi"
This fixes whitespace in the index, while preserving the index, and
leaving the tree untouched. With this alias, you can fix unversioned
files in the repo with
git add --all :/ && git fixws && git reset
But, it also handles the more common case of fixing up whitespace in a
commit you're working on. It's complicated because it works even when
the index or tree are clean.
If you use emacs, you can use "M^x delete-trailing-whitespace" to delete them before saving the file. (it can be customized in your .emacs also)
vi seems to also allow this : http://vim.wikia.com/wiki/Remove_unwanted_spaces