From: Harald Nordgren Date: Wed, 3 Jun 2026 09:04:36 +0000 (+0000) Subject: branch: prepare delete_branches for a bulk caller X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=4d70f2d269fe6f0e7aa580fa8746f5fb9fa857d1;p=thirdparty%2Fgit.git branch: prepare delete_branches for a bulk caller Add no_head_fallback and dry_run flags to delete_branches() so a bulk caller (the upcoming --prune-merged) can ask strictly about merged-into-upstream without a silent fallback to HEAD, and rehearse deletions with the same "Would delete branch ..." wording as the live run. Existing callers pass 0 for both and keep current behavior. When no_head_fallback is set, head_rev stays NULL through to branch_merged(), whose "merged to X but not yet merged to HEAD" reminder otherwise compares against HEAD. For the bulk caller every candidate is known to have an upstream, so HEAD is irrelevant. Guard the block on head_rev so the NULL case skips it instead of treating "NULL != reference_rev" as "diverges from HEAD" and emitting a spurious warning. Signed-off-by: Harald Nordgren Signed-off-by: Junio C Hamano --- diff --git a/builtin/branch.c b/builtin/branch.c index 93d8eae891..09afdd9257 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -169,10 +169,13 @@ static int branch_merged(int kind, const char *name, * upstream, if any, otherwise with HEAD", we should just * return the result of the repo_in_merge_bases() above without * any of the following code, but during the transition period, - * a gentle reminder is in order. + * a gentle reminder is in order. Callers that opt out of the + * HEAD fallback by passing head_rev=NULL are not interested in + * the reminder either: they have already established that the + * branch has an upstream, so HEAD is irrelevant to the decision. */ - if (head_rev != reference_rev) { - int expect = head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0; + if (head_rev && head_rev != reference_rev) { + int expect = repo_in_merge_bases(the_repository, rev, head_rev); if (expect < 0) exit(128); if (expect == merged) @@ -225,7 +228,8 @@ static void delete_branch_config(const char *branchname) } static int delete_branches(int argc, const char **argv, int force, int kinds, - int quiet, int warn_only) + int quiet, int warn_only, int no_head_fallback, + int dry_run) { struct commit *head_rev = NULL; struct object_id oid; @@ -259,7 +263,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, } branch_name_pos = strcspn(fmt, "%"); - if (!force) + if (!force && !no_head_fallback) head_rev = lookup_commit_reference(the_repository, &head_oid); for (i = 0; i < argc; i++, strbuf_reset(&bname)) { @@ -330,13 +334,20 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, free(target); } - if (refs_delete_refs(get_main_ref_store(the_repository), NULL, &refs_to_delete, REF_NO_DEREF)) + if (!dry_run && + refs_delete_refs(get_main_ref_store(the_repository), NULL, &refs_to_delete, REF_NO_DEREF)) ret = 1; for_each_string_list_item(item, &refs_to_delete) { char *describe_ref = item->util; char *name = item->string; - if (!refs_ref_exists(get_main_ref_store(the_repository), name)) { + if (dry_run) { + if (!quiet) + printf(remote_branch + ? _("Would delete remote-tracking branch %s (was %s).\n") + : _("Would delete branch %s (was %s).\n"), + name + branch_name_pos, describe_ref); + } else if (!refs_ref_exists(get_main_ref_store(the_repository), name)) { char *refname = name + branch_name_pos; if (!quiet) printf(remote_branch @@ -1003,7 +1014,7 @@ int cmd_branch(int argc, if (!argc) die(_("branch name required")); ret = delete_branches(argc, argv, delete > 1, filter.kind, - quiet, 0); + quiet, 0, 0, 0); goto out; } else if (show_current) { print_current_branch_name();