Thread (119 messages) 119 messages, 6 authors, 11h ago

Re: [PATCH v7 11/11] builtin/history: implement "drop" subcommand

From: Junio C Hamano <hidden>
Date: 2026-06-29 19:49:46

Patrick Steinhardt [off-list ref] writes:
+static int find_head_tree_change(struct repository *repo,
+				 const struct replay_result *result,
+				 struct commit **old_head,
+				 struct commit **new_head,
+				 bool *changed)
+{
+	const struct replay_ref_update *head_update = NULL;
+	struct commit *old_head_commit, *new_head_commit;
+	struct tree *old_head_tree, *new_head_tree;
+	const char *head_target;
+	int head_flags;
+
+	*changed = false;
+
+	head_target = refs_resolve_ref_unsafe(get_main_ref_store(repo),
+					      "HEAD", RESOLVE_REF_NO_RECURSE,
+					      NULL, &head_flags);
+	if (!head_target)
+		return error(_("cannot look up HEAD"));
Here head_target would be something like "refs/heads/master", or
whatever the "HEAD" happens to point at.
+	if (!(head_flags & REF_ISSYMREF))
+		head_target = "HEAD";
But if it is not a symref, then it is a detached HEAD.  We manually
set it to "HEAD" again.  We know head_target was not NULL, so what
did we receive in it from refs_resolve_ref_unsafe() call, before we
overwrite it here?
+	for (size_t i = 0; i < result->updates_nr; i++) {
+		if (!strcmp(result->updates[i].refname, head_target)) {
+			head_update = &result->updates[i];
+			break;
+		}
+	}
We see if we are going to update the currently checked out branch.

The .updates[] array was earlier populated by the caller that called
compute_pending_ref_updates() before it called us.
+	if (!head_update)
+		return 0;
And we return if not.  That is a simple and happy case.  Otherwise
we'd tell the caller about the updated commit and tree (strictly
speaking that would be redundant, but since we have it already, it
is better to give them to the caller instead of forcing the caller
to unwrap the commit).
+static int cmd_history_drop(int argc,
+			    const char **argv,
+			    const char *prefix,
+			    struct repository *repo)
+{
+...
+	struct option options[] = {
+		OPT_CALLBACK_F(0, "update-refs", &action, "(branches|head)",
+			       N_("control which refs should be updated"),
+			       PARSE_OPT_NONEG, parse_ref_action),
...
+		OPT_END(),
+	};
...
+	ret = compute_pending_ref_updates(&revs, action, original, rewritten,
+					  empty, &result);
Here we call the function.  When action is "--update-refs=head",
doesn't this code in compute_pending_ref_updates() ... 

		if (action == REF_ACTION_HEAD &&
		    decoration->type != DECORATION_REF_HEAD)
			continue;

... skip any reference name (loaded by load_ref_decorations() lazily
by calling get_name_decoration()) that is not "HEAD", which would
mean we end up not finding any hits in the find_head_tree_change()
function call we make later ...
+	if (ret) {
+		ret = error(_("failed replaying descendants"));
+		goto out;
+	}
+ ...
+	if (!is_bare_repository()) {
+		ret = find_head_tree_change(repo, &result, &old_head,
+					    &new_head, &head_moves);
... here?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help