branch: prepare delete_branches for a bulk caller

Teach delete_branches() two new modes for the upcoming
--delete-merged: one that asks only whether a branch is merged into
its upstream, without falling back to HEAD when there is no
upstream, and one that rehearses the deletions without removing any
ref. Existing callers keep their current behavior.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Harald Nordgren
2026-06-18 19:25:26 +00:00
committed by Junio C Hamano
parent 81078ea37f
commit 7745859fcf
+20 -6
View File
@@ -168,10 +168,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)
@@ -193,6 +196,8 @@ enum delete_branch_flags {
DELETE_BRANCH_FORCE = (1 << 0),
DELETE_BRANCH_QUIET = (1 << 1),
DELETE_BRANCH_SKIP_UNMERGED = (1 << 2),
DELETE_BRANCH_NO_HEAD_FALLBACK = (1 << 3),
DELETE_BRANCH_DRY_RUN = (1 << 4),
};
static int check_branch_commit(const char *branchname, const char *refname,
@@ -241,6 +246,8 @@ static int delete_branches(int argc, const char **argv, int kinds,
bool force;
bool quiet = flags & DELETE_BRANCH_QUIET;
bool skip_unmerged = flags & DELETE_BRANCH_SKIP_UNMERGED;
bool dry_run = flags & DELETE_BRANCH_DRY_RUN;
bool no_head_fallback = flags & DELETE_BRANCH_NO_HEAD_FALLBACK;
struct strbuf bname = STRBUF_INIT;
enum interpret_branch_kind allowed_interpret;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
@@ -268,7 +275,7 @@ static int delete_branches(int argc, const char **argv, int kinds,
force = flags & DELETE_BRANCH_FORCE;
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)) {
@@ -339,13 +346,20 @@ static int delete_branches(int argc, const char **argv, 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