Imagine a pre-commit hook that should strictly prevent committing incorrectly formatted code. A scrap of it could look as follows:
clang_format() { configuration="${PWD}/.clang-format" if [ -r "${configuration}" ]; then if [ -n "$(parse --verify 'HEAD' 2> '/dev/null')" ]; then commit='HEAD' else commit='4b825dc642cb6eb9a060e54bf8d69288fbee4904' fi extensions=... git clang-format --staged \ --commit="${commit}" \ --extensions="${extensions}" \ --style='file' \ "${@}" else die '%s: %s: %s' \ 'clang-format' \ 'Configuration file not found' \ "${configuration}" fi } ... set -e diff="$(clang_format --diff)" set +e if [ "${diff}" != 'no modified files to format' ] && \ [ "${diff}" != 'clang-format did not modify any files' ]; then error="$(clang_format 2>&1 > /dev/null)" die "%s: %s\n%s${error:+\n}%s" \ 'clang-format' \ 'Code style issues detected' \ "${error}" \ "${diff}" fi
Here is what happens without the new --staged option:
- Stage badly formatted source file;
- git commit;
- The above pre-commit hook will:
- report error (abort commit),
- reformat code accordingly,
- and print the corresponding diff;
- Don't stage the newly formatted changes (which correspond to the correct expected formatting to be committed);
- git commit (success).
Notice how commit succeeds and git-clang-format does not detect wrong formatting anymore. It happens because along with staged changes it also considers not staged changes, including the ones that it just has made itself. Thus, it thinks everything is OK with the source code and lets one commit it while part of this correct formatting was not even staged for the commit. Clearly, this is unlikely to be the behavior one would expect in this use case.
NOTE:
--force option has nothing to do with this problem.
With the new --staged option, git-clang-format is instructed to consider only staged changes when performing formatting or producing diffs. As a result, no matter how many times one issues git commit, they all will be aborted until one stages the correctly formatted code.
This will work without --diff (otherwise it will try to apply changes in the index to the working directory, which doesn't make sense), so could you please add a check that --staged requires --diff?