When you are using Git commit validation (a.k.a. commit linting) and it fails, it is frustrating to re-type your message. Git stores the commit message that failed validation in .git/COMMIT_EDITMSG
. You can use this stored message to start your new commit message with
git commit -e --file=$(git rev-parse --git-dir)/COMMIT_EDITMSG
On a recent project, they had husky commit linting with some aggressive rules. It was maddening when my commit failed and I had to re-type it. This command saved me a lot of time.
How it Works
–file tells Git what file to use for the commit message
-e tells Git to load the commit message in the editor (instead of using the message without editing)
$(git rev-parse --git-dir)
returns the path to the local Git directory (if you’re in the root of the project, this will be .git
)
Skipping the Commit Validation
As an alternative, depending on the project, you can skip the commit validation by adding the –no-verify parameter.
e.g.
git commit --no-verify
How Git Commit Validation Works
Git supports a number of hooks that are run at certain times. Specifically, if you add an executable file at .git/hooks/commit-msg
it will run whenever you save a commit message. If this executable file exits with an error code, the commit will fail.
e.g.
#!/bin/sh
# Fail commit message validation every time.
echo 'Commit message validation failed'
exit 1
While writing this post, I created the above file at .git/hooks/commit-msg
and made it executable with
chmod 744 .git/hooks/commit-msg
This caused my commit validation to fail every time. Deleting .git/hooks/commit-msg
removes this failing validation.
Adding an alias
You can add a Git alias for this command by running the following from the command line.
git config --global alias.recover-rejected-commit '!f() { git commit -e --file=$(git rev-parse --git-dir)/COMMIT_EDITMSG; }; f'
After this, you can run
git recover-rejected-commit
to start your commit message with the contents of the previously failed commit message.
Thanks for this, it’s a nice, clearly written explanation and solution, and it saved my butt today! I even integrated an adapted version of this into an NPM script on the project that burned me and added a note to the commit linter, so that others after me wouldn’t suffer the same fate: https://github.com/sequelize/sequelize/pull/13953