Log in

February 23rd, 2009

Previous Entry Share Next Entry
05:13 pm - Fun with whitespaces
Often people stumble across the sample pre-commit hook that enforces strict whitespace breakage checks in their repositories. I blame binary packaged git in some distributions for this. None of the sample hook is meant to be enabled by default.

In any case, if you see complaints on whitespace breakage when you try to commit, the first thing you should do is to think.  Does your project care about what the whitespace check warns about?

The sample implements the rule used by the Linux kernel and the git project, but your project may have different rules.  The easiest workaround would be to disable the sample hook if what it does does not suit your needs, by:

$ mv .git/hooks/pre-commit .git/hooks/pre-commit.disabled

In any case, if you find .git/hooks/pre-commit has a long Perl script in it, and if you are using a decently recent git (that is, 1.6.0 or newer), it means your repository was initialized long time ago, and you may want to replace the pre-commit hook with the sample shipped with more recent one. You can keep using the old one, but the new one is much more robust than the old Perl script.

The easiest way to do it would be:

$ mkdir /tmp/junk && cd /tmp/junk && git init

and look at .git/hooks/pre-commit.sample that is in there.  It should use "git diff --check" instead of a Perl script to do its job.

The whitespace rules implemented in the sample hook are that of the Linux kernel and the git project.  They are:
  1. Whitespaces at the end of line (trailing-space).  Most programming languages and documentation text do not change semantics with or without them, so do not have trailing whitespaces;

  3. Space before tab in the initial indentation (space-before-tab).  For example, a SP followed by a HT followed by "A" at the beginning of the line would look identical to a HT followed by "A" at the beginning of the line, and most programming languages and documentation text do not change semantics between the two, so do not have space before tab in the initial indentation;

  5. Indent with spaces (indent-with-non-tab).  Both in the Linux kernel and git project a HT by definition skips to the next column that is multiple of 8.  Eight SP at the beginning of the line is frowned upon and a HT at the beginning of the line is preferred.

Some or none of them may apply to your project, and you can selectively disable them. You can even selectively enable/disable them on a per filetype basis, using the attributes mechanism.  For example, if you want the above Linux kernel style rules for all of your C source files, but you want to allow indentation with SP in your text files and Python scripts, you would have something like this in your .gitattributes file at the toplevel of your source tree (and "git add" it, so that other repositories that work on this project will consistently use these rules you set up):

*.[ch] trailing-space space-before-tab indent-with-non-tab
*.py trailing-space space-before-tab -indent-with-non-tab
*.txt trailing-space space-before-tab -indent-with-non-tab

In addition, by default git considers that the end-of-line is denoted by a LF, not by a CR-LF.  If you track DOS formatted text without using core.autocrlf conversion, the data you record in the repository will have lines that have trailing CR and because CR is a whitespace character, you will trigger trailing space errors.  You can tell git that you are deliberately recording contents with CR-LF by adding 'cr-at-eol' attribute in your .gitattribute file, like this:

* cr-at-eol

Note that this does not apply if you record lines without CR using core.autocrlf, even when the files in your work tree do use CR-LF line endings (this is useful to keep your project cross-platform).  Diff output from such a project will not have CR at the end of line, and you do not need to use cr-at-eol attributes.

After making changes, but before trying "git add" or "git commit", you can check if you have made these whitespace breakages by running "git diff --check".  Also, if you enable "color.ui" (or "color.diff"), "git diff" will highlight such whitespace errors.  To check the contents that are staged for the next commit, you can say "git diff --cached" to ask for differences between the staged contents in the cache and the current HEAD commit.

Now, if you set up the white-space error detection correctly, you would want to fix errors you make yourself before committing them.  It is a topic on a separate entry.

(3 comments | Leave a comment)


Date:February 25th, 2009 04:40 pm (UTC)

Minor typo

From the documentation here:


it looks like the color config variables are "color.ui" and "color.diff" (not "ui.color" and "diff.color").

Best regards,
[User Picture]
Date:February 27th, 2009 09:07 am (UTC)

Re: Minor typo

Thanks; fixed.
Date:January 31st, 2011 06:40 am (UTC)

Bardzo pouczajace

dobry poczatek
Fun with whitespaces - gitster's journal

> Recent Entries
> Archive
> Friends
> Profile

Pages at the k.org
The latest blog by Gitster

> Go to Top