git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git revert --continue --no-verify

From
PWPhillip Wood <phillip.wood123@gmail.com>
Date
Aug 4, 2021, 18:14 UTC
Message-ID
<74443c64-efe9-ea47-e918-d62b8c976abc@gmail.com>
In-Reply-To
<YQm+PWAtc3rixqsw@nand.local>
Hi Cameron and Taylor
On 03/08/2021 23:07, Taylor Blau wrote:
> On Tue, Aug 03, 2021 at 04:33:09PM -0500, Cameron Steffen wrote:
>> Perhaps the issue then is that the pre-commit hook should not run for
>> `git revert --continue`? It does not run for `git revert`.

The general rule for cherry-pick, revert and rebase is that if the commit message is edited then the commit is made with --verify and if the commit message is not being edited then the commit is made with --no-verify. I think the reasoning for this is that if the user has altered the commit message or contents and they have a pre-commit hook set then it is reasonable to check the new commit is acceptable to the hook. There are some exceptions to this which are oversights (for example I think we always pass --no-verify when committing a conflict resolution with 'git rebase --continue' even though the editor opens when committing in that case - I should try and fix that)

For 'git revert --continue' the commit is made when sequencer_continue() calls continue_single_pick() which looks like

static int continue_single_pick(struct repository *r, struct replay_opts 
*opts)
{
	struct strvec argv = STRVEC_INIT;
	int ret;
	if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
	    !refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
		return error(_("no cherry-pick or revert in progress"));
	strvec_push(&argv, "commit");
	/*
	 * continue_single_pick() handles the case of recovering from a
	 * conflict.  should_edit() doesn't handle that case; for a conflict,
	 * we want to edit if the user asked for it, or if they didn't specify
	 * and stdin is a tty.
	 */
	if (!opts->edit || (opts->edit < 0 && !isatty(0)))
		/*
		 * Include --cleanup=strip as well because we don't want the
		 * "# Conflicts:" messages.
		 */
		strvec_pushl(&argv, "--no-edit", "--cleanup=strip", NULL);
	ret = run_command_v_opt(argv.v, RUN_GIT_CMD);
	strvec_clear(&argv);
	return ret;
}

It runs git commit directly and never passes --no-verify. I wouldn't be opposed to someone adding support for --no-verify (and --no-edit) to "cherry-pick/revert/rebase --continue" on the understanding that it only applied when committing the conflict resolution. There is a possible confusion for users though who might expect that the options passed with '--continue' applied to all the commits made by the command.

> This does look like an oversight to me, but you'll have to bear with me
> since I am relatively unfamiliar with the sequencer code.
> 
> Ultimately `git revert` calls do_pick_commit()

This is what happens when we are picking commits, the commit made with '--continue' uses a different code path

Show 10 quoted lines
> which either calls
> do_commit() or run_git_commit(). A couple of curiosities there:
> 
>    - do_commit() does fall back to run_git_commit() if it has the
>      VERIFY_MSG bit set in `flags`.
>    - run_git_commit() passes `-n` only when VERIFY_MSG *isn't* set, so
>      the VERIFY_MSG bit does imply that the pre-commit hook would be run
>      there.
>    - when do_pick_commit() does have to fall back to run_git_commit(), it
>      sets the VERIFY_MSG bit in flags.

Calling run_git_commit() there is not a fallback it, that call is used to reword commits once they have been picked (see 450efe2d53 ("rebase -i: always update HEAD before rewording", 2019-08-19) for the reasoning behind this) . Because the message is being edited there is no point in going through do_commit().

Show 7 quoted lines
> But we never end up calling run_git_commit() (except in the case of
> errors) because do_pick_commit() special-cases `command == TODO_REVERT`
> (which is the case for `git revert`) and calls `do_commit()`.
> 
> But it gets weirder: do_commit() calls run_git_commit() itself, but
> before the caller in do_pick_commit() has had a chance to add VERIFY_MSG
> to the flags.

do_commit() does not change the flags that it is called with - callers that want VERIFY_MSG will set that before they call do_commit(). do_commit() is there to commit simple picks without forking 'git commit'

> So I suspect that this is an oversight, but perhaps somebody more
> familiar with this code could confirm my thinking.

I hope the above helps - basically the idea is "if the commit has been edited use VERIFY_MSG" and --continue unhelpfully uses a completely different code-path to the main commit picking/reverting loop.

Best Wishes
Phillip
> Thanks,
> Taylor
> 
Previous: Junio C HamanoNext: Taylor Blau
Message 8 of 10 in “git revert --continue --no-verify”
  1. Cameron SteffenAug 3, 2021
  2. Taylor BlauAug 3, 2021
  3. Cameron SteffenAug 3, 2021
  4. Taylor BlauAug 3, 2021
  5. Cameron SteffenAug 3, 2021
  6. Taylor BlauAug 3, 2021
  7. Junio C HamanoAug 4, 2021
  8. Phillip WoodAug 4, 2021
  9. Taylor BlauAug 5, 2021
  10. Cameron SteffenAug 5, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.