Git Hooks
- Summary
-
Discussion
- What use cases can benefit from Git Hooks?
- What are client-side and server-side hooks?
- What are pre- and post- Git Hooks?
- What options help skip the execution of hooks?
- What essentials should a developer know to use Git Hooks?
- What does it take to create and maintain reusable Git Hooks?
- How do I configure my project environment to use Git Hooks?
- What are some criticisms of Git Hooks?
- Milestones
- References
- Further Reading
- Article Stats
- Cite As
Hooks in Git are executable scripts that are triggered when certain events happen in Git. It's a way to customize Git's internal behaviour, automate tasks, enforce policies, and bring consistency across the team.
For example, hooks can check that passwords or access tokens are not committed, validate that commit messages conform to an agreed format, prevent unauthorized developers from pushing to a branch, update local directories after a checkout, and so on.
Git supports both client-side and server-side hooks. Hooks can be written in any programming language though it's common to use Bash, Perl, Python or Ruby.
Discussion
-
What use cases can benefit from Git Hooks? The figure illustrates local add/commit followed by a push to the remote repository. Also shown are the relevant hooks. Each hook is given a specific name. Hooks are invoked by naming convention before or after specific events.
The
pre-commit
hook is called when the commit procedure begins. This hook can format the code against the project's styling guide, run linting or execute unit tests. By checking for missing semicolons, trailing whitespace, and debug statements code reviews can focus on more important issues. Hooksprepare-commit-msg
andcommit-msg
can be used to format/validate the commit message.After a successful commit, the hook
post-commit
could be used to send notifications. More commonly, when collaboration is via a remote repository, notifications are sent from thepost-receive
hook that's triggered after all references are updated. This hook can also deploy the latest changes to production. Theupdate
hook that runs once per branch can be used to enforce access control, that is, only authorized users can push to a branch. -
What are client-side and server-side hooks? Client-side hooks run on developer machines whereas server-side hooks run on the server that hosts the repository. Committing, merging, rebasing, applying patches, and checkout are common Git operations that developers do on their development machines. Any of these commands can trigger their relevant client-side hooks. Server-side hooks are triggered by the
git-receive-pack
command, which is a result of developers pushing changes to the remote repository on a cloud-hosted Git server.Developers have full control of client-side hooks. Developers can choose to disable all client-side hooks if they wish. If a project's best practices need to be strictly enforced, server-side hooks are the way to do it.
Some Git repository providers impose restrictions on the use of server-side hooks on their cloud-based servers. For example, GitHub's free tier doesn't allow developers to define server-side hooks though GitHub Enterprise Server supports them. However, there are alternatives to achieve server-side automation such as webhooks, GitHub Apps/Actions, GitLab CI/CD, GitLab push rules, etc.
-
What are pre-
andpost-
Git Hooks?Client-side and server-side hooks can be either
pre-
andpost-
hooks. Thepre-
hooks can be used to validate stuff before allowing the requested operation. For example,pre-commit
hook executes at the start of a commit workflow. If the commit is deemed invalid for any reason, the hook can return a non-zero value. This terminates the commit operation. By returning zero, the hook states that the commit operation can continue, including the execution of other relevant hooks.The
post-
hooks execute after the requested operation is done. Such a hook's return value doesn't matter since the operation is already complete. For example,post-commit
executes after a successful commit. These hooks are typically used to send emails or other notifications. They may also be used to trigger CI/CD pipelines. For example,post-receive
could be used to deploy the updated code to production. -
What options help skip the execution of hooks? It's possible to skip some hooks if their associated commands are called with certain options. Hooks
pre-commit
,pre-merge-commit
,prepare-commit-msg
, andcommit-msg
can be skipped ifcommit
andmerge
commands are invoked with--no-verify
option.The hook
post-checkout
can be skipped ifclone
andworktree add
commands are called with--no-checkout
option. However, this hook is always called forcheckout
andswitch
commands. -
What essentials should a developer know to use Git Hooks? By default, hooks are stored in
.git/hooks
within the project's repository. Git populates this folder with sample scripts that developers can use as a starting point. However, the file suffix.sample
must be removed and scripts must be made executable. Developers can rewrite the scripts in their preferred language. Accordingly, the shebang (#!
first line in script) must be updated with the correct path to the language.If these sample scripts are deleted by mistake, we can retrieve them from Git templates folder. This may be
/usr/local/git-core/templates/hooks
(Linux) orC:\Program Files\Git\mingw64\share\git-core\templates\hooks
(Windows). In fact, this copying from templates folder to the project's.git/
folder is what happens when we rungit init
.While hooks are triggered in response to specific events, we can also manually trigger the execution of a hook. The command for this is
git hook run <hook-name> <hook-args>
. For example, we could trigger one hook from another hook. This command is a low-level internal helper command.Beginners can start by reading the official documentation on Git Hooks and Chapter 14 of Loeliger's book on Git.
-
What does it take to create and maintain reusable Git Hooks? It's a good practice to commit hooks as part of the repository so that all developers reuse and execute the same hooks. However, it's not permitted to store them within a
.git/hooks
folder within the repository. One approach is store them in another folder, sayhooks
, and then create a soft link from.git/hooks
tohooks
folder after cloning the repository. Another approach is to configure the path to the hooks with the commandgit config core.hooksPath <path>
.To reuse across projects, hooks can be in a separate repository and cloned locally. Configure the hooks path globally to that folder:
git config --global core.hooksPath <path>
. This configuration variable has been available since Git version 2.9.0.There's also a framework named pre-commit to manage pre-commit hooks. This framework includes dozens of tested pre-commit hooks written in Python that developers can reuse in their own projects. These include syntax checking (
check-json
,check-yaml
), fixing problems (fix-byte-order-marker
,trailing-whitespace
), protecting secrets (detect-private-key
,detect-aws-credentials
), enforcing policies (no-commit-to-branch
,forbid-new-submodules
), and more.The githooks.com lists many useful hooks and related tools that developers can use.
-
How do I configure my project environment to use Git Hooks? No special configuration is needed other than updating
.git/hooks
folder or configuringcore.hooksPath
variable. However, many developer tools attempt to simplify this further.In Maven, a plugin can setup the hooks path. In Gradle, we can have a dependent build script to do this setup. In Node.js, Husky project allows us to wire up all the hooks in the
package.json
file. In PHP, hooks can be set up incomposer.json
file via thepost-install-cmd
configuration.In different languages, frameworks are available to manage hooks: pre-commit (Python), Overcommit (Ruby), Lefthook (Ruby or Node.js).
-
What are some criticisms of Git Hooks? Hooks change Git's default behaviour. If a hook does something unusual, it may confuse developers new to the project. Moreover, hooks can be buggy and make things counterproductive. For this reason, some recommend using Git aliases and invoking scripts directly rather than relying on hooks.
Git doesn't provide any easy mechanism to share hooks among developers or from one repository to another. No doubt this is more secure but at the expense of convenience and reusability. Hooks problem with installation, maintainability, and reusability is to some extent solved by frameworks such as pre-commit.
Hooks are powerful. Developers may be tempted to run unit tests before each commit. This can slow things quite a bit and discourage developers from committing often. This can lead to data loss.
Server-side hooks are not universally enabled by cloud-hosted Git repository service providers.
Milestones
2007
2007
2008
2008
2009
2014
A critical vulnerability is discovered pertaining to Git hooks. Usually it's not possible to create a top-level folder named .git
in a repository. However, in case-sensitive filesystems it's possible to create a folder named .GIT
, .Git
, etc. In Windows, which is case-insensitive, such a folder overwrites the default .git
folder. By including malicious hooks, a hacker could execute arbitrary code on the client's machine. This threat is greatest for developers using third party or untrusted repositories. This vulnerability is patched within a week.
2015
2016
2016
2019
2022
On GitHub, it's noticed that pushes to repositories can take as long as 880ms on average. The implementation is in Ruby. A lot of time is spent loading Ruby dependencies. By rewriting the hook as a Go service, average processing time is brought down to 10ms. This improvement also becomes part of GitHub Enterprise Server 3.4.
References
- AK DevCraft. 2021. "Git pre-hook: Setup pre-commit hook for Gradle project example." Dev.to, September 17. Updated 2021-12-17. Accessed 2022-05-06.
- Atlassian. 2022. "Git Hooks." Tutorial, Atlassian. Accessed 2022-05-06.
- Brown, Zack. 2018. "A Git Origin Story." Linux Journal, July 27. Accessed 2022-05-06.
- Bréhin, Maxime. 2017. "Addicted to Hooks." Blog, Delicious Insights, April 14. Updated 2022-05-05. Accessed 2022-05-06.
- Florence, Ryan. 2010. "Deploying Websites With a Tiny Git Hook." July 27. Accessed 2022-05-06.
- Git. 2005. "History for git/run-command.c." v1.0.0, Git, on GitHub, December 8. Accessed 2022-05-06.
- Git. 2010a. "GIT v1.5.4 Release Notes." Git, on GitHub, September 7. Accessed 2022-05-06.
- Git. 2010b. "GIT v1.6.0 Release Notes." Git, on GitHub, September 7. Accessed 2022-05-06.
- Git. 2012. "GIT v1.6.1 Release Notes." Git, on GitHub, October 16. Accessed 2022-05-06.
- Git. 2019a. "GIT v1.6.3 Release Notes." Git, on GitHub, December 3. Accessed 2022-05-06.
- Git. 2019b. "Git 2.24 Release Notes." Git, on GitHub, October 31. Accessed 2022-05-06.
- Git. 2019c. "Git 2.9 Release Notes." Git, on GitHub, December 3. Accessed 2022-05-06.
- Git. 2022. "Tags." Git, on GitHub. Accessed 2022-05-06.
- Git SCM. 2022a. "githooks - Hooks used by Git." Documentation, Git SCM, v2.36.0, April 18. Accessed 2022-05-06.
- Git SCM. 2022b. "gitrepository-layout - Git Repository Layout." Documentation, Git SCM, v2.36.0, April 18. Accessed 2022-05-06.
- Git SCM. 2022c. "git - the stupid content tracker." Documentation, Git SCM, v2.36.0, April 18. Accessed 2022-05-06.
- Git SCM. 2022d. "git-hook - Run git hooks." Documentation, Git SCM, v2.36.0, April 18. Accessed 2022-05-06.
- Git SCM. 2022e. "git-init - Create an empty Git repository or reinitialize an existing one." Documentation, Git SCM, v2.36.0, April 18. Accessed 2022-05-06.
- GitHub. 2017. "Release notes for the 2.6 series." GitHub Enterprise 2.6.20, April 18. Accessed 2022-05-06.
- GitHub. 2022. "GitHub Enterprise Server releases." Documentation, Enterprise Server 3.4, GitHub. Accessed 2022-05-06.
- GitLab. 2022. "Server hooks." Documentation, GitLab, February 14. Accessed 2022-05-06.
- Haggerty, Michael. 2015. "Git 2.4 — atomic pushes, push to deploy, and more." Blog, GitHub, April 30. Accessed 2022-05-06.
- Hettiarachchi, Charith. 2020. "Git pre-commits hooks and Continous Integration / Continous Deployment." On Medium, February 22. Accessed 2022-05-06.
- Leimonis, Konstantinos. 2019. "How To Ease Your Team’s Development Workflow With Git Hooks." Smashing Magazine, December 2. Accessed 2022-05-06.
- Loeliger, Jon. 2009. "Version Control with Git." First Edition, O'Reilly. Accessed 2022-05-06.
- Mphego, Mpho. 2019. "Why You Need To Stop Using Git-Hooks." Blog, October 3. Accessed 2022-05-06.
- Nieto, Carlos Martín and Thomas Gummerer. 2022. "Improving Git push times through faster server side hooks." Blog, GitHub, April 21. Accessed 2022-05-06.
- Pettersen, Tim. 2014. "Securing your Git server against CVE-2014-9390." Blog, Atlassian, December 20. Accessed 2022-05-06.
- Straub, Ben, and Scott Chacon. 2014a. "8.3 Customizing Git - Git Hooks." Second Edition, Apress. Accessed 2022-05-06.
- Straub, Ben, and Scott Chacon. 2014b. "8.4 Customizing Git - An Example Git-Enforced Policy." Second Edition, Apress. Accessed 2022-05-06.
- de Rivas, Fernando Moya. 2022. "Enforce Your Team’s Code-style With Git Hooks." Better Programming, on Medium, March 9. Accessed 2022-05-06.
- pre-commit. 2022a. "Homepage." pre-commit. Accessed 2022-05-06.
- pre-commit. 2022b. "pre-commit-hooks." pre-commit, on GitHub, May 3. Accessed 2022-05-06.
- shabunc. 2010. "Putting Git hooks into a repository." StackOverflow, August 11. Updated 2021-12-29. Accessed 2022-05-06.
Further Reading
- Git SCM. 2022a. "githooks - Hooks used by Git." Documentation, Git SCM, v2.36.0, April 18. Accessed 2022-05-06.
- Atlassian. 2022. "Git Hooks." Tutorial, Atlassian. Accessed 2022-05-06.
- Tran, Tony and Justin Ellingwood. 2014. "How To Use Git Hooks To Automate Development and Deployment Tasks." Tutorial, Digital Ocean, August 12. Updated 2022-03-10. Accessed 2022-05-06.
- Leimonis, Konstantinos. 2019. "How To Ease Your Team’s Development Workflow With Git Hooks." Smashing Magazine, December 2. Accessed 2022-05-06.
- Prajapati, Ameet. 2020. "Understanding Git Hooks." Codeburst, on Medium, May 16. Accessed 2022-05-06.
Article Stats
Cite As
See Also
- Git
- GitHub Actions
- Shell Scripting
- Automated Code Review
- Automatic Code Comment Generation
- Continuous Integration