A very common use case for hooks in git is a pre-commit
hook. This hook is used to verify the to-be-committed data before it is added to the repository.
One important note: hooks are not part of the repository itself. Everyone can install a hook on it’s own checkout of a repository, but by default the hook is not there when you clone/checkout the repository. This avoids security problems by executing arbitrary code during git commit
, or any git
operation.
Because of this implication it is common that developers install a hook from somewhere in the repository into the .git/hooks
directory. And in addition, the server side (the repository) can run the same checks during git push
, to enforce the rules.
Hooks in git work in a simple way: whatever program or script is run as the hook has to set a return code. If the return code is 0
, git proceeds. If it’s not 0
, git aborts the operation.
Back to the hook: the first problem is how to identify the to-be-committed files? “git diff” lists the files:
|
|
The options:
--staged
: lists all files which are stated for the next commit.--staged
is an alias for--cached
, both versions can be used.--name-only
: lists only the filenames, not the entire diff.--diff-filter
: selects what kind of files will be included in the diff.A
: Added filesC
: Copied filesM
: Modified files
The git diff
above does not select Renamed
or Deleted
files. A renamed file might violate naming rules, in this case you have to include this option as well. And a deleted file is about to be removed from the repository, and most likely does not need to be checked.
Let’s put this all together into a small shell script which runs as the git hook. In my example I want to enforce two things:
- No double spaces in the file
- No spaces at the end of the line
Here is the .git/hooks/pre-commit
example:
|
|
The first part identifies the changed files. The loop runs over all changed files, and checks them for the two conditons. The $exit_status
variable is set by any error. Finally the last if-then-else
part returns an error if there is any problem in the files.