
Why You *Really* Need a Pre-Commit Script for Your PHP Projects
Scott Keck-Warren • June 9, 2025
Despite what we tell others we’ve all pushed something to production we probably shouldn’t have. A missing semicolon, a rogue var_dump()
, and even an unused use
statement or two just sitting there like it owns the place. These little mistakes are SO easy to miss but can cause huge problems for us and our subscribers. By using a pre-commit script we can reduce if not completely eliminate some of these issues.
What’s a Pre-Commit Script?
A pre-commit script is one of the hooks that Git gives us to interrupt its lifecycle and add your own logic. Specifically, a pre-commit
script runs before you’re allowed to create a commit to see if the code is still in a valid state. It provides you with one last line of defense to catch simple problems early.
In a PHP-based project, this is a great opportunity to run static code analysis (SCA) tools like:
It's easy to run these tools on our files before we create the commit but it's even easy to be lazy and skip them so we want to make sure we automate these using make
and a very simple pre-commit
script.
Using a "Makefile" to Organize Your Pre-commit
Tasks
We've discussed make
and "Makefiles" in "What is the make
Command in Linux?" but as a quick refresher:
make
is a build automation tool. It reads instructions from a file called "Makefile" and runs the commands you and your team define there. While it originated in the C programming world to compile and link source code, at its coremake
can be used as a general-purpose task runner. If you write a "Makefile" with steps to run PHPUnit, lint code, or compile SCSS,make
will happily do that for you.
The important piece is that it "can be used as a general-purpose task runner". I use make
to run my SCA tools locally and include them in every project I set up. Below is the current "Makefile" from https://github.com/warren5236/ScottsValueObjects which tends to be the starting point for when I roll out checks for my teams:
## PreCommit Section
CHANGED_PHP_FILES = git diff --diff-filter=AM --staged --name-only src tests scripts | grep ".php"
pre-commit: lint_changed phpcs_changed phpstan_changed rector_changed
lint_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/parallel-lint
phpcs_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpcs --standard=phpcs.xml
phpstan_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpstan analyze --memory-limit 1G
rector_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/rector process --dry-run
## Full Static Code Analysis Section
phpcbf:
vendor/bin/phpcbf --standard=phpcs.xml src tests scripts
phpstan:
vendor/bin/phpstan analyze --memory-limit 1G -l9 src tests
This allows us to run make pre-commit
at the command line and it will run a variety of SCA tools on just the files that we have staged for the commit (that's what git diff --diff-filter=AM --staged --name-only src tests scripts | grep ".php"
) is responsible for.
Feel free to use the above file as a starting point for your project and add or remove pieces that you need.
Installing the Git Pre-Commit Hook
The missing piece is that we still don't have a pre-commit
script we just have a "Makefile" that does the work for us but we still need to "wire it up" so it's part of the flow.
To do that create a file at .git/hooks/pre-commit
with the following:
#!/bin/sh
make pre-commit
Then make it executable:
chmod +x .git/hooks/pre-commit
To add some additional robustness (and make sure it gets installed consistently) you can also write the minimal pre-commit
script from above into "scripts/pre-commit" and then install it using the "post-install-cmd" section of your "composer.json" scripts:
"scripts": {
"post-install-cmd": [
"cp ./scripts/pre-commit .git/hooks/",
"chmod +x .git/hooks/pre-commit"
]
}
Now every time you run git commit
, your pre-commit
script will run make pre-commit
and perform checks on your code before it can be committed.
% git commit -a
git diff --diff-filter=AM --staged --name-only src tests scripts | grep ".php" | xargs vendor/bin/phpcs --standard=phpcs.xml
FILE: /Users/scottkeck-warren/Projects/ScottsValueObjects/src/Location/City.php
-------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
-------------------------------------------------------------------------------
22 | ERROR | [x] Whitespace found at end of line
-------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
-------------------------------------------------------------------------------
If you haven’t already set this up in your PHP project, now’s the perfect time. Your teammates (and your future self) will thank you.
This was originally published at https://phpdeveloperstv.substack.com/p/why-you-really-need-a-pre-commit