From: Patrick Steinhardt Date: Wed, 1 Jul 2026 11:35:33 +0000 (+0200) Subject: reset: introduce ability to skip updating HEAD X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b2ebb7803bafb581649de1b51eb3184ab7fe3463;p=thirdparty%2Fgit.git reset: introduce ability to skip updating HEAD In a subsequent commit we'll introduce a new caller to `reset_working_tree()` that really only wants to update the index and working tree, without updating any references. Introduce a new flag that makes the caller opt in to updating HEAD and adapt all callers to set that flag. Note that in a previous iteration we instead introduced a flag that made callers opt out of updating any references. This was somewhat awkward though because we already have the `UPDATE_ORIG_HEAD` flag, so the result was somewhat inconsistent. Suggested-by: Phillip Wood Signed-off-by: Patrick Steinhardt [jc: fixed-up a typo pointed out by Christian] Signed-off-by: Junio C Hamano --- diff --git a/builtin/rebase.c b/builtin/rebase.c index 06dcbaf5e8..10a306310c 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -607,7 +607,8 @@ static int move_to_original_branch(struct rebase_options *opts) strbuf_addf(&head_reflog, "%s (finish): returning to %s", opts->reflog_action, opts->head_name); ropts.branch = opts->head_name; - ropts.flags = RESET_WORKING_TREE_REFS_ONLY; + ropts.flags = RESET_WORKING_TREE_REFS_ONLY | + RESET_WORKING_TREE_UPDATE_HEAD; ropts.branch_msg = branch_reflog.buf; ropts.head_msg = head_reflog.buf; ret = reset_working_tree(the_repository, &ropts); @@ -693,6 +694,7 @@ static int run_am(struct rebase_options *opts) ropts.oid = &opts->orig_head->object.oid; ropts.branch = opts->head_name; ropts.default_reflog_action = opts->reflog_action; + ropts.flags = RESET_WORKING_TREE_UPDATE_HEAD; reset_working_tree(the_repository, &ropts); error(_("\ngit encountered an error while preparing the " "patches to replay\n" @@ -862,7 +864,8 @@ static int checkout_up_to_date(struct rebase_options *options) options->reflog_action, options->switch_to); ropts.oid = &options->orig_head->object.oid; ropts.branch = options->head_name; - ropts.flags = RESET_WORKING_TREE_RUN_POST_CHECKOUT_HOOK; + ropts.flags = RESET_WORKING_TREE_RUN_POST_CHECKOUT_HOOK | + RESET_WORKING_TREE_UPDATE_HEAD; if (!ropts.branch) ropts.flags |= RESET_WORKING_TREE_DETACH; ropts.head_msg = buf.buf; @@ -1384,7 +1387,8 @@ int cmd_rebase(int argc, rerere_clear(the_repository, &merge_rr); string_list_clear(&merge_rr, 1); - ropts.flags = RESET_WORKING_TREE_HARD; + ropts.flags = RESET_WORKING_TREE_HARD | + RESET_WORKING_TREE_UPDATE_HEAD; if (reset_working_tree(the_repository, &ropts) < 0) die(_("could not discard worktree changes")); remove_branch_state(the_repository, 0); @@ -1409,7 +1413,8 @@ int cmd_rebase(int argc, ropts.oid = &options.orig_head->object.oid; ropts.head_msg = head_msg.buf; ropts.branch = options.head_name; - ropts.flags = RESET_WORKING_TREE_HARD; + ropts.flags = RESET_WORKING_TREE_HARD | + RESET_WORKING_TREE_UPDATE_HEAD; if (reset_working_tree(the_repository, &ropts) < 0) die(_("could not move back to %s"), oid_to_hex(&options.orig_head->object.oid)); @@ -1877,6 +1882,7 @@ int cmd_rebase(int argc, ropts.oid = &options.onto->object.oid; ropts.orig_head = &options.orig_head->object.oid; ropts.flags = RESET_WORKING_TREE_DETACH | + RESET_WORKING_TREE_UPDATE_HEAD | RESET_WORKING_TREE_UPDATE_ORIG_HEAD | RESET_WORKING_TREE_RUN_POST_CHECKOUT_HOOK; ropts.head_msg = msg.buf; diff --git a/reset.c b/reset.c index 99f2c1b012..490194380e 100644 --- a/reset.c +++ b/reset.c @@ -92,6 +92,7 @@ int reset_working_tree(struct repository *r, const char *switch_to_branch = opts->branch; unsigned reset_hard = opts->flags & RESET_WORKING_TREE_HARD; unsigned refs_only = opts->flags & RESET_WORKING_TREE_REFS_ONLY; + unsigned update_head = opts->flags & RESET_WORKING_TREE_UPDATE_HEAD; unsigned update_orig_head = opts->flags & RESET_WORKING_TREE_UPDATE_ORIG_HEAD; unsigned dry_run = opts->flags & RESET_WORKING_TREE_DRY_RUN; struct object_id *head = NULL, head_oid; @@ -113,6 +114,9 @@ int reset_working_tree(struct repository *r, if (opts->branch_msg && !opts->branch) BUG("branch reflog message given without a branch"); + if (update_orig_head && !update_head) + BUG("cannot update ORIG_HEAD without updating HEAD"); + if (!refs_only && !dry_run && repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) { ret = -1; goto leave_reset_head; @@ -129,7 +133,7 @@ int reset_working_tree(struct repository *r, oid = &head_oid; if (refs_only) { - if (!dry_run) + if (!dry_run && update_head) return update_refs(r, opts, oid, head); return 0; } @@ -197,7 +201,8 @@ int reset_working_tree(struct repository *r, goto leave_reset_head; } - if (oid != &head_oid || update_orig_head || switch_to_branch) + if (update_head && + (oid != &head_oid || update_orig_head || switch_to_branch)) ret = update_refs(r, opts, oid, head); leave_reset_head: diff --git a/reset.h b/reset.h index 898e4a1e95..38b2891b53 100644 --- a/reset.h +++ b/reset.h @@ -19,14 +19,17 @@ enum reset_working_tree_flags { /* Only update refs, do not touch the worktree */ RESET_WORKING_TREE_REFS_ONLY = (1 << 3), - /* Update ORIG_HEAD as well as HEAD */ - RESET_WORKING_TREE_UPDATE_ORIG_HEAD = (1 << 4), + /* Update HEAD */ + RESET_WORKING_TREE_UPDATE_HEAD = (1 << 4), + + /* Update ORIG_HEAD */ + RESET_WORKING_TREE_UPDATE_ORIG_HEAD = (1 << 5), /* * Perform a dry-run by performing the operation without updating * any user-visible state. */ - RESET_WORKING_TREE_DRY_RUN = (1 << 5), + RESET_WORKING_TREE_DRY_RUN = (1 << 6), }; struct reset_working_tree_options { diff --git a/sequencer.c b/sequencer.c index 4efe831178..e905b1b2d9 100644 --- a/sequencer.c +++ b/sequencer.c @@ -4678,7 +4678,8 @@ static void create_autostash_internal(struct repository *r, has_uncommitted_changes(r, 1)) { struct child_process stash = CHILD_PROCESS_INIT; struct reset_working_tree_options ropts = { - .flags = RESET_WORKING_TREE_HARD, + .flags = RESET_WORKING_TREE_HARD | + RESET_WORKING_TREE_UPDATE_HEAD, }; struct object_id oid; @@ -4873,6 +4874,7 @@ static int checkout_onto(struct repository *r, struct replay_opts *opts, .oid = onto, .orig_head = orig_head, .flags = RESET_WORKING_TREE_DETACH | + RESET_WORKING_TREE_UPDATE_HEAD | RESET_WORKING_TREE_UPDATE_ORIG_HEAD | RESET_WORKING_TREE_RUN_POST_CHECKOUT_HOOK, .head_msg = reflog_message(opts, "start", "checkout %s",