]> git.ipfire.org Git - thirdparty/git.git/commitdiff
branch: prepare delete_branches for a bulk caller
authorHarald Nordgren <haraldnordgren@gmail.com>
Wed, 3 Jun 2026 09:04:36 +0000 (09:04 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Jun 2026 10:10:05 +0000 (19:10 +0900)
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 <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/branch.c

index 93d8eae89107704013a105bfc322fad57b5aace7..09afdd925758462f6d4b84666eee6aa4d580ce38 100644 (file)
@@ -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();