Regarding githooks, I had 3 different goals:
- 📜 Verify that my commits respect the expected format (hook n°1)
- 🔧 Check unit tests are green before every
git push(hook n°2)
- 👥 Share these hooks with my team
Just for the record, my project was made with Symfony/PHP, and launched via docker/docker-compose.
But since the main goal here is to use githooks, you can adapt following lines for your own context and needs 😃
ℹ️ Note: Once a
git init is made on your project folder, you can find githooks examples in
./.git/hooks in folder as
With my team, we decided to use specific commit formats in order to facilitate the way to consult our git history.
Here are the formats:
## Example of a commit linked to a specific ticket [PSBO-723] An amazing commit message ## Example of a commit linked to a hotfix [hotfix] A hot message for a hot commit
First, I need to create a regex that matches only these formats:
Then I have to create the githooks that will check the commit message format every time I will try to commit.
To do it I create the hook file as
.git/hooks/commit-msg in my project folder:
#!/usr/bin/env bash echo "Checking commit-message format..." ## the first arg is the path to the git commit temporary file TEMPORARY_FILE_PATH=$1 ## get commit-message from the temporary file COMMIT_MSG=`head -n1 $TEMPORARY_FILE_PATH` ## init regex to match commit-message format REGEX="^\[(hotfix|\w+\-[0-9]+)\]( \w+)+$" ## checking commit-message format if ! [[ $COMMIT_MSG =~ $REGEX ]];then echo -e "Your commit-message format is not valid:\n$COMMIT_MSG\n" echo "Valid format examples:" echo "[PSBO-123] My commit message" echo "[hotfix] My commit message" exit 1 else echo "Well done! Your commit-message is valid." exit 0 fi
Once done, don't forget to give to the file the right to be executed.
sudo chmod +x .git/hooks/commit-msg
Now, if I try to commit with an invalid message:
git commit -m "Yehaaaa"
Checking commit-message format... Your commit-message format is not valid: Yehaaaa Valid format examples: [PSBO-123] My commit message [hotfix] My commit message
And the commit is canceled, as expected! 🎉
If I try to commit with a valid message:
git commit -m "[PSBO-456] It's a valid one this time"
Checking commit-message format... Well done! Your commit-message is valid.
And the commit is done! ✔️
Let's do it again!
Since I want to check unit tests before pushing my code, I will create a hook file as
#!/usr/bin/env bash echo "Checking unit-tests..." ## checking unit-tests cd ./infra || exit if sudo docker-compose run php bin/phpunit;then echo "Well done, unit-tests are green!" echo "'git push' is now done." exit 0 else echo "Unit-tests failed, therefore the push is canceled." echo "Please fix them before pushing again." exit 1 fi
Once again, I need to give this hook file the right to be executed.
sudo chmod +x .git/hooks/pre-push
So, let's check if it works in case my unit tests are failing.
First, I changed the code of a unit test so that it fails.
Now I try to git push to trigger the hook:
git add . git commit -m "[hotfix] Breaking unit-tests" git push origin develop
Checking unit-tests... Creating infra_php_run ... done Testing Project Test Suite F 1 / 1 (100%) There was 1 failure: 1) App\Tests\Util\CalculatorTest::testCalculate Failed asserting that 15 is identical to 16. /var/www/tests/Util/CalculatorTest.php:31 FAILURES! Tests: 1, Assertions: 1, Failures: 1. ERROR: 1 Unit-tests failed, therefore the push is canceled. Please fix them before pushing again.
Tests failed, so the push is canceled, seems good! 👍
OK, this time I fixed the code of the unit test.
Then I push to trigger the hook once again:
git add . git commit -m "[hotfix] Fixing unit-tests" git push origin develop
Checking unit-tests... Creating infra_php_run ... done Testing Project Test Suite . 1 / 1 (100%) OK (1 test, 1 assertion) Well done, unit-tests are green! 'git push' is now done.
Unit-tests are green, so the push was validated and done! This hook works as planned! 💃
Now, my hooks are ready!
But unfortunately I can't share them with the team.
Because githooks are ignored by git (as every other file in
.git folder), therefore they can't be added to the index or be commited in anyway...
Unless we do some little magic! 🎩 🐰
ℹ️ Note: There are multiple solutions to solve this issue, I picked this one because I found it smart and easy to set up.
So to do the magic, I'm going to create my own githooks folder in the root path of the project (not in the
## I create my own githooks folder mkdir .githooks ## Then, move the githooks I created in this new folder mv .git/hooks/commit-msg .githooks/ mv .git/hooks/pre-push .githooks/ ## Don't forget to give "execute" right to the files, if not already done sudo chmod +x .githooks/*
Now, I just need to tell git where to find my githooks files:
## Specify a folder for hooks (only available for git version >= 2.9) git config core.hooksPath .githooks
And it's done!
From now one, I can commit these hooks since there are no longer ignored by git, so my teammates will be able to use them.
My githooks work, and I can share them with my team, it's all good! 🎉 💥
Hope this helped you find out how githooks work and how powerful they can be.