I use a pre-commit
hook to run Prettier
formatter against my HTML
documents:
#!/bin/sh
# Retrieving a list of the staged files
stagedFiles=$(git diff --staged --name-only)
# Format staged files automatically
echo "Formatting with Prettier..."
npx prettier --write $stagedFiles
git add $stagedFiles
The formatting successfully applies right after I enter git commit
command and right before my configured editor opens the commit message. According to commit.verbose
setting, Git
appends there a diff showing what is to be committed, but this diff does not take into account changes made by Prettier
— it demonstrates the unformatted version of my code. If I then abort the commit (leaving the message empty), I can see that no unstaged changes are in the repository; it means that all formatting modifications had been properly staged during execution of the pre-commit
hook. Moreover, if I write some text to the message and complete the commit without aborting, the resulting snapshot does contain all formatting that was missing in the diff.
I finally concluded that the diff lies. But does a solution exist?
Git for Windows
version: 2.33.0
OS: Windows 10 21h1 x64
The short answer is : the pre-commit
hook is not intended to modify files to be committed.
You can relate to the following rationale : the content you commit will be the exact content you could review and test before running git commit
.
(the technical reason is : git
creates the tree -- the content for the commit -- that will be used before calling the pre-commit
hook)
A pre-commit
hook should be written as a read-only action, which may prevent the commit from happening, e.g : if a file is not formatted correctly, reject the commit with a message "please run format.sh
before committing".
Of course, you could work your way around that, but, FWIW, I advise you to follow this rule.