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

Re: [PATCH v2 03/14] rebase: pass correct arguments to post-checkout hook

From
Junio C Hamano <gitster@pobox.com>
Date
Dec 9, 2021, 18:53 UTC
Message-ID
<xmqqa6h9sj8e.fsf@gitster.g>
In-Reply-To
<07867760e68a6b28f718bdcb33094461592affaa.1638975482.git.gitgitgadget@gmail.com>
"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 11 quoted lines
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> If a rebase started with "rebase [--apply|--merge] <upstream> <branch>"
> detects that <upstream> is an ancestor of <branch> then it fast-forwards
> and checks out <branch>. Unfortunately in that case it passed the null
> oid as the first argument to the post-checkout hook rather than the oid
> of HEAD.
>
> A side effect of this change is that the call to update_ref() which
> updates HEAD now always receives the old value of HEAD. This provides
> protection against another process updating HEAD during the checkout.
Nicely described.
Show 40 quoted lines
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  reset.c                       | 18 +++++++++---------
>  t/t5403-post-checkout-hook.sh | 13 +++++++++++++
>  2 files changed, 22 insertions(+), 9 deletions(-)
>
> diff --git a/reset.c b/reset.c
> index f214df3d96c..315fef91d33 100644
> --- a/reset.c
> +++ b/reset.c
> @@ -18,7 +18,7 @@ int reset_head(struct repository *r, struct object_id *oid, const char *action,
>  	unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
>  	unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
>  	unsigned update_orig_head = flags & RESET_ORIG_HEAD;
> -	struct object_id head_oid;
> +	struct object_id *head = NULL, head_oid;
>  	struct tree_desc desc[2] = { { NULL }, { NULL } };
>  	struct lock_file lock = LOCK_INIT;
>  	struct unpack_trees_options unpack_tree_opts = { 0 };
> @@ -26,8 +26,7 @@ int reset_head(struct repository *r, struct object_id *oid, const char *action,
>  	const char *reflog_action;
>  	struct strbuf msg = STRBUF_INIT;
>  	size_t prefix_len;
> -	struct object_id *orig = NULL, oid_orig,
> -		*old_orig = NULL, oid_old_orig;
> +	struct object_id *old_orig = NULL, oid_old_orig;
>  	int ret = 0, nr = 0;
>  
>  	if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
> @@ -38,7 +37,9 @@ int reset_head(struct repository *r, struct object_id *oid, const char *action,
>  		goto leave_reset_head;
>  	}
>  
> -	if ((!oid || !reset_hard) && get_oid("HEAD", &head_oid)) {
> +	if (!get_oid("HEAD", &head_oid)) {
> +		head = &head_oid;
> +	} else if (!oid || !reset_hard) {
>  		ret = error(_("could not determine HEAD revision"));
>  		goto leave_reset_head;
>  	}

Here, the original grabbed head_oid only when oid is not known or we are not doing a hard reset. Now we grab head_oid when available, regardless of the other conditions. But the logic to error out is the same. If oid is not given or not doing hard reset, it is an error if we cannot figure out what object HEAD points at (is that "unborn branch"?).

OK.
Show 16 quoted lines
> @@ -98,13 +99,12 @@ reset_head_refs:
>  	if (update_orig_head) {
>  		if (!get_oid("ORIG_HEAD", &oid_old_orig))
>  			old_orig = &oid_old_orig;
> -		if (!get_oid("HEAD", &oid_orig)) {
> -			orig = &oid_orig;
> +		if (head) {
>  			if (!reflog_orig_head) {
>  				strbuf_addstr(&msg, "updating ORIG_HEAD");
>  				reflog_orig_head = msg.buf;
>  			}
> -			update_ref(reflog_orig_head, "ORIG_HEAD", orig,
> +			update_ref(reflog_orig_head, "ORIG_HEAD", head,
>  				   old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
>  		} else if (old_orig)
>  			delete_ref(NULL, "ORIG_HEAD", old_orig, 0);

The variable 'orig' was initialized to NULL and then got assigned the value of HEAD here, which is used in update_ref(). The new code does the same thing with the 'head' variable that we have already prepared earlier. So there is no change here locally, but this affects correctness later ...

Show 8 quoted lines
> @@ -116,7 +116,7 @@ reset_head_refs:
>  		reflog_head = msg.buf;
>  	}
>  	if (!switch_to_branch)
> -		ret = update_ref(reflog_head, "HEAD", oid, orig,
> +		ret = update_ref(reflog_head, "HEAD", oid, head,
>  				 detach_head ? REF_NO_DEREF : 0,
>  				 UPDATE_REFS_MSG_ON_ERR);

... here. In the original code, there is nothing that populates the 'orig' variable, if "update_orig_head" is not true, so we used to pass NULL here. Now as long as we know what HEAD is, we pass use it.

Show 6 quoted lines
> @@ -128,7 +128,7 @@ reset_head_refs:
>  	}
>  	if (run_hook)
>  		run_hook_le(NULL, "post-checkout",
> -			    oid_to_hex(orig ? orig : null_oid()),
> +			    oid_to_hex(head ? head : null_oid()),
And the same fix is in effect here.
Nice.
Show 24 quoted lines
> diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
> index 272b02687ba..17ab518f268 100755
> --- a/t/t5403-post-checkout-hook.sh
> +++ b/t/t5403-post-checkout-hook.sh
> @@ -72,6 +72,19 @@ test_rebase () {
>  		test_cmp_rev rebase-on-me $new &&
>  		test $flag = 1
>  	'
> +
> +	test_expect_success "rebase $args fast-forward branch checkout runs post-checkout hook" '
> +		test_when_finished "test_might_fail git rebase --abort" &&
> +		test_when_finished "rm -f .git/post-checkout.args" &&
> +		git update-ref refs/heads/rebase-fast-forward three &&
> +		git checkout two  &&
> +		rm -f .git/post-checkout.args &&
> +		git rebase $args HEAD rebase-fast-forward  &&
> +		read old new flag <.git/post-checkout.args &&
> +		test_cmp_rev two $old &&
> +		test_cmp_rev three $new &&
> +		test $flag = 1
> +	'
>  }
>  
>  test_rebase --apply &&
Previous: Phillip Wood via GitGitGadgetNext: Phillip Wood via GitGitGadget
Message 43 of 85 in “rebase: reset_head() related fixes and improvements”
  1. 00/11 rebase: reset_head() related fixes and improvementsPhillip Wood via GitGitGadget, Oct 1, 2021
  2. 01/11 rebase: factor out checkout for up to date branchPhillip Wood via GitGitGadget, Oct 1, 2021
  3. 03/11 reset_head(): don't run checkout hook if there is an errorPhillip Wood via GitGitGadget, Oct 1, 2021
  4. Junio C HamanoOct 1, 2021
  5. Phillip WoodOct 4, 2021
  6. Ævar Arnfjörð BjarmasonOct 12, 2021
  7. 04/11 reset_head(): remove action parameterPhillip Wood via GitGitGadget, Oct 1, 2021
  8. Junio C HamanoOct 1, 2021
  9. Phillip WoodOct 4, 2021
  10. 05/11 reset_head(): factor out ref updatesPhillip Wood via GitGitGadget, Oct 1, 2021
  11. Junio C HamanoOct 1, 2021
  12. Phillip WoodOct 4, 2021
  13. 06/11 reset_head(): make default_reflog_action optionalPhillip Wood via GitGitGadget, Oct 1, 2021
  14. Junio C HamanoOct 1, 2021
  15. Junio C HamanoOct 1, 2021
  16. Phillip WoodOct 4, 2021
  17. 09/11 rebase --apply: fix reflogPhillip Wood via GitGitGadget, Oct 1, 2021
  18. Junio C HamanoOct 1, 2021
  19. 08/11 reset_head(): take struct rebase_head_optsPhillip Wood via GitGitGadget, Oct 1, 2021
  20. Junio C HamanoOct 1, 2021
  21. Phillip WoodOct 4, 2021
  22. 10/11 rebase --apply: set ORIG_HEAD correctlyPhillip Wood via GitGitGadget, Oct 1, 2021
  23. Junio C HamanoOct 1, 2021
  24. 02/11 reset_head(): fix checkoutPhillip Wood via GitGitGadget, Oct 1, 2021
  25. Junio C HamanoOct 1, 2021
  26. Phillip WoodOct 4, 2021
  27. Junio C HamanoOct 4, 2021
  28. Eric SunshineOct 1, 2021
  29. 11/11 rebase -m: don't fork git checkoutPhillip Wood via GitGitGadget, Oct 1, 2021
  30. 07/11 rebase: cleanup reset_head() callsPhillip Wood via GitGitGadget, Oct 1, 2021
  31. Junio C HamanoOct 2, 2021
  32. Junio C HamanoOct 2, 2021
  33. Phillip WoodOct 2, 2021
  34. Phillip WoodOct 2, 2021
  35. René ScharfeOct 2, 2021
  36. Phillip WoodOct 6, 2021
  37. 00/14 rebase: reset_head() related fixes and improvementsPhillip Wood via GitGitGadget, Dec 8, 2021
  38. 01/14 rebase: factor out checkout for up to date branchPhillip Wood via GitGitGadget, Dec 8, 2021
  39. Junio C HamanoDec 9, 2021
  40. 02/14 t5403: refactor rebase post-checkout hook testsPhillip Wood via GitGitGadget, Dec 8, 2021
  41. Junio C HamanoDec 9, 2021
  42. 03/14 rebase: pass correct arguments to post-checkout hookPhillip Wood via GitGitGadget, Dec 8, 2021
  43. Junio C HamanoDec 9, 2021
  44. 04/14 rebase: do not remove untracked files on checkoutPhillip Wood via GitGitGadget, Dec 8, 2021
  45. Junio C HamanoDec 9, 2021
  46. 05/14 rebase --apply: don't run post-checkout hook if there is an errorPhillip Wood via GitGitGadget, Dec 8, 2021
  47. 06/14 reset_head(): remove action parameterPhillip Wood via GitGitGadget, Dec 8, 2021
  48. 07/14 create_autostash(): remove unneeded parameterPhillip Wood via GitGitGadget, Dec 8, 2021
  49. Junio C HamanoDec 9, 2021
  50. Phillip WoodJan 25, 2022
  51. 08/14 reset_head(): factor out ref updatesPhillip Wood via GitGitGadget, Dec 8, 2021
  52. 09/14 reset_head(): make default_reflog_action optionalPhillip Wood via GitGitGadget, Dec 8, 2021
  53. Junio C HamanoDec 9, 2021
  54. 10/14 rebase: cleanup reset_head() callsPhillip Wood via GitGitGadget, Dec 8, 2021
  55. Junio C HamanoDec 9, 2021
  56. Phillip WoodJan 25, 2022
  57. 11/14 reset_head(): take struct rebase_head_optsPhillip Wood via GitGitGadget, Dec 8, 2021
  58. Junio C HamanoDec 9, 2021
  59. 12/14 rebase --apply: fix reflogPhillip Wood via GitGitGadget, Dec 8, 2021
  60. Junio C HamanoDec 9, 2021
  61. 13/14 rebase --apply: set ORIG_HEAD correctlyPhillip Wood via GitGitGadget, Dec 8, 2021
  62. Elijah NewrenDec 11, 2021
  63. 14/14 rebase -m: don't fork git checkoutPhillip Wood via GitGitGadget, Dec 8, 2021
  64. Junio C HamanoDec 9, 2021
  65. Phillip WoodJan 26, 2022
  66. Junio C HamanoJan 27, 2022
  67. Elijah NewrenDec 11, 2021
  68. 00/14 rebase: reset_head() related fixes and improvementsPhillip Wood via GitGitGadget, Jan 26, 2022
  69. 01/14 rebase: factor out checkout for up to date branchPhillip Wood via GitGitGadget, Jan 26, 2022
  70. 02/14 t5403: refactor rebase post-checkout hook testsPhillip Wood via GitGitGadget, Jan 26, 2022
  71. 03/14 rebase: pass correct arguments to post-checkout hookPhillip Wood via GitGitGadget, Jan 26, 2022
  72. 04/14 rebase: do not remove untracked files on checkoutPhillip Wood via GitGitGadget, Jan 26, 2022
  73. 05/14 rebase --apply: don't run post-checkout hook if there is an errorPhillip Wood via GitGitGadget, Jan 26, 2022
  74. 06/14 reset_head(): remove action parameterPhillip Wood via GitGitGadget, Jan 26, 2022
  75. 07/14 reset_head(): factor out ref updatesPhillip Wood via GitGitGadget, Jan 26, 2022
  76. 08/14 reset_head(): make default_reflog_action optionalPhillip Wood via GitGitGadget, Jan 26, 2022
  77. 09/14 create_autostash(): remove unneeded parameterPhillip Wood via GitGitGadget, Jan 26, 2022
  78. 10/14 rebase: cleanup reset_head() callsPhillip Wood via GitGitGadget, Jan 26, 2022
  79. 11/14 reset_head(): take struct rebase_head_optsPhillip Wood via GitGitGadget, Jan 26, 2022
  80. Ævar Arnfjörð BjarmasonJan 26, 2022
  81. Phillip WoodJan 26, 2022
  82. 12/14 rebase --apply: fix reflogPhillip Wood via GitGitGadget, Jan 26, 2022
  83. 13/14 rebase --apply: set ORIG_HEAD correctlyPhillip Wood via GitGitGadget, Jan 26, 2022
  84. 14/14 rebase -m: don't fork git checkoutPhillip Wood via GitGitGadget, Jan 26, 2022
  85. Elijah NewrenFeb 1, 2022

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.