Have you ever considered how useful it would be if some actions could be taken automatically before or after a git commit, push, merge, etc.? Well, the good news is that it’s possible and also very straightforward using a lesser-known yet powerful feature of git – Git Hooks.
Understanding Git Hooks
Hooks are programs you can place in a hooks directory to trigger actions at certain points in git’s execution.
They are basically scripts that are (by default) found in the $GIT_DIR/hooks directory. When events such as commits or pushes occur, git automatically runs the corresponding hooks, enabling developers to customize their behavior. After writing your code inside the appropriate hook script, it needs to be named accordingly (without the `.sample` extension), and it needs to be executable. There are two types of git hooks: client-side and server-side.
Client-side hooks are triggered by operations such as committing and merging, so they’re running on your local machine, while server-side hooks run on network operations such as receiving pushed commits, so on the git server. That is nicely represented with figure 1.
Figure 1. Graphical representation of client-side and server-side git hooks (source)
Git hooks can also be categorized as pre- or post-hooks. Pre-hooks are invoked before a certain git operation happens and, as such, have the option to cancel the operation if necessary. Post-hooks, on the other hand, are invoked after git operations and, therefore, can not cancel them, but they can be used to automate parts of a workflow.
Practical examples
Imagine a scenario where you have a bare git server on a remote machine used by multiple users. On that git server, you push files that are needed on another location on that same remote machine, and you want to automate the process so that whenever someone pushes changes to the git server, the files on the appropriate location are updated. That’s an ideal task for a git hook script. Since the script is to be invoked after a git operation, it is a post hook, and since it’s supposed to happen after a git push, it’s also a server-side git hook.
The steps to set up that kind of hook are:
1. Access the Git Server
First, you need to gain access to the remote machine where the git server is hosted. Ensure that you have the necessary permissions to modify the git repository and create hook scripts.
2. Locate the Hooks Directory
In the git server repository, navigate to the “hooks” directory. This is where all the hook scripts are stored.
3. Write the Post-Receive Hook Script
Create a new file named “post-receive” (with no file extension) within the “hooks” directory. This file will contain the custom script that handles the file synchronization.
4. Implement the Custom Script
Inside the “post-receive” file, you’ll write the script to update the files in the desired location. Depending on your specific setup, you might use shell commands or a programming language of your choice to achieve this.
5. Make the Script Executable
Remember to make the script executable using the appropriate permissions. This ensures that it can be run as intended.
6. Test the Hook
With the script in place, it’s time to test the post-receive hook! Make some changes to the Git repository, commit them, and then push the changes to the server. You should see the magic happening as the files in the appropriate location are automatically updated.
The custom script from step 4 can be something like this:
#!/bin/bash TARGET="/home/test" GIT_DIR="/home/test/project.git" BRANCH="main" while read oldValue newValue refName do # only checking out the main if [ "${refName}" = "refs/heads/$BRANCH" ]; then echo "Ref ${refName} received. Moving files from ${BRANCH} to ${TARGET}..." git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH else echo "Ref ${refName} received. Only watching ${BRANCH}." fi done
By harnessing the power of server-side git hooks, the development workflow is streamlined, eliminating the need for manual updates.
Another scenarios where git hooks are useful are:
- Enforcing Commit Message Format:
A pre-commit hook can be implemented to enforce a specific commit message format, making it easier for team members to understand the purpose of each commit.
- Running Tests:
Utilizing a pre-push hook to run unit tests ensures that only code passing the tests is pushed to the remote repository, reducing the chances of introducing bugs.
- Preventing Sensitive Data from Being Committed:
A pre-commit hook can be set up to scan code changes for any instances of sensitive data (e.g., API keys or passwords) and prevent the commit if such data is found.
Conclusion
In conclusion, Git hooks offer a powerful way to customize and automate actions in your development process. From pre-commit checks to post-receive deployments, Git hooks can significantly streamline collaboration and enhance code quality. By leveraging these hooks effectively, you can enforce standards, run tests automatically, and integrate with CI/CD pipelines. Embrace the power of git hooks to boost efficiency and take your development workflow to the next level.
Challenge
Join the challenge and visit Atlantbh’s office! Authors of the three best solutions matching acceptance criteria will get a chance to meet our Talent team.
Task
Imagine a scenario where you work on a collaborative project using git for versioning files. To maintain clarity and organization within the project, you want to enforce a standardized commit message format.
You want to commit messages to be in the format:
<type>:<description>
and to have a maximum of 50 characters.
As for the commit type, you offer:
- feature (new feature)
- fix (bug fix)
- refactor (refactoring code)
- wip (work in progress – commits to be pushed later)
Solve this using git hooks.
Hint: use `commit-msg` hook.
Acceptance Criteria
- Create public GitHub repository
- Add Readme explaining the solution
- Create required git-hook in this repository
- Send us your GitHub repository link through the application form until October 15 2023.
*Atlantbh does not cover the cost of transportation to the office.
“Git Hooks” Tech Bite was brought to you by Ena Pirija, DevOps Engineer at Atlantbh.
Tech Bites are tips, tricks, snippets or explanations about various programming technologies and paradigms, which can help engineers with their everyday job.