]> git.ipfire.org Git - thirdparty/git.git/commitdiff
branch: prepare delete_branches for a bulk caller
authorHarald Nordgren <haraldnordgren@gmail.com>
Fri, 22 May 2026 11:31:35 +0000 (11:31 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sun, 24 May 2026 08:41:07 +0000 (17:41 +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.  That reminder is only
meaningful when the caller actually cares about HEAD; for the
bulk caller every candidate is known to have an upstream and HEAD
is irrelevant to the decision.  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 96f6ae6dec41f9efa90660eba5898893e3a7d092..08c12376244995a9d26797d921bdd986e6a2a737 100644 (file)
@@ -170,10 +170,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)
@@ -226,7 +229,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;
@@ -260,7 +264,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)) {
@@ -331,13 +335,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
@@ -1027,7 +1038,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 (forked) {
                ret = list_forked_branches(argc, argv);