Re: [PATCH] add: support pre-add hook
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Feb 10, 2026, 19:00 UTC
- Message-ID
- <xmqq8qd0zan1.fsf@gitster.g>
- In-Reply-To
- <xmqqldh0zcpa.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> writes:
Show 5 quoted lines
> The hook takes no clue from anything derived from the command line, > not even the pathspec (or list of individual paths computed using > the pathspec by the command) or the mode of operation like '-u' or > '--renormalize'. I am not sure how effective a decision the invoked > hook can make to approve or deny in this lack of information.
And I do not necessarily suggest passing the pathspec arguments or command line options that the "git add" command received from its caller down to the hook, which will force hook authors to emulate what "git add" would do to these arguments and options, and they will certainly get it wrong.
I wonder if we can split write_locked_index() into two so that writing out the in-core index to the temporary/lockfile can happen separately from the call to commit_locked_index(). If we can do so, then the following would become a viable and better implementation of this new feature to run the "pre-add" hook:
* Determine if we will need to run this "pre-add" hook, at the location in the code you addded the run_hooks_opt() invocation, but do *NOT* run any hook there yet.
* Instead, create a temporary copy of the index file if the above says "Yes, we are going to run the hook".
* Let the code path to update the in-core index, i.e., letting everythning up to the "finish:" label to run normally.
* Perform the first-half of the write_locked_index(), writing the new index contents into the lockfile, but stopping before committing it to the final name.
* If we are running the hook, run it with two arguments, the name of the temporary copy of the original index we created earlier, and the name of this lockfile that has the proposed contents of the index if the hook allowed "git add" to proceed.
* If we ran the hook and hook succeeded, or if we did not have to run the hook at all, then commit the lockfile. Otherwise abort the "git add" command and rollback_lock_file().
* Remove the temporary file we created earlier (if any).
Your hooks can "GIT_INDEX_FILE=$1 git diff --cached --name-only" to find out which paths already had changes added before this invocation of "git add", and similarly using $2 get the list of paths that will add further changes with this invocation. The latter set of paths you can inspect to see if you like the additional changes brought in, perhaps like
#!/bin/sh
paths=$(GIT_INDEX_FILE=$2 git diff --cached --name-only)
GIT_INDEX_FILE=$1 git diff $paths >patch.txt if grep "^+.*secret" patch.txt
then
echo "do not divulge company secret!" >&2
exit 1
fior something.