[PATCH v27 0/2] status: add status.compareBranches config for multiple branch comparisons
From: Harald Nordgren via GitGitGadget <hidden>
Date: 2026-01-22 15:37:23
cc: Chris Torek chris.torek@gmail.com cc: Yee Cheng Chin
ychin.macvim@gmail.com cc: "brian m. carlson" sandals@crustytoothpaste.net
cc: Ben Knoble ben.knoble@gmail.com cc: "Kristoffer Haugsbakk"
kristofferhaugsbakk@fastmail.com cc: Phillip Wood phillip.wood123@gmail.com
cc: Nico Williams nico@cryptonector.com cc: Patrick Steinhardt ps@pks.im cc:
Jeff King peff@peff.net
Harald Nordgren (2):
refactor format_branch_comparison in preparation
status: add status.compareBranches config for multiple branch
comparisons
Documentation/config/status.adoc | 20 ++
remote.c | 192 ++++++++++++++----
t/t6040-tracking-info.sh | 337 +++++++++++++++++++++++++++++++
3 files changed, 512 insertions(+), 37 deletions(-)
base-commit: b5c409c40f1595e3e590760c6f14a16b6683e22c
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2138%2FHaraldNordgren%2Fahead_of_main_status-v27
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2138/HaraldNordgren/ahead_of_main_status-v27
Pull-Request: https://github.com/git/git/pull/2138
Range-diff vs v26:
1: 27a46f8d9c = 1: 27a46f8d9c refactor format_branch_comparison in preparation
2: caa761f615 ! 2: 0993420fc1 status: add status.compareBranches config for multiple branch comparisons
@@ remote.c
struct counted_string {
size_t len;
const char *s;
-@@ remote.c: static void branch_release(struct branch *branch)
- free((char *)branch->refname);
- free(branch->remote_name);
- free(branch->pushremote_name);
-+ free((char *)branch->push_tracking_ref);
- merge_clear(branch);
- }
-
@@ remote.c: int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
return stat_branch_pair(branch->refname, base, num_ours, num_theirs, abf);
}
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
- const char *full_base;
- char *base;
- int upstream_is_gone = 0;
--
++ char *compare_branches = NULL;
++ struct string_list branches = STRING_LIST_INIT_DUP;
++ struct string_list processed_refs = STRING_LIST_INIT_DUP;
++ int reported = 0;
++ size_t i;
++ const char *upstream_ref;
++ const char *push_ref;
+
- cmp_fetch = stat_tracking_info(branch, &ours, &theirs, &full_base, 0, abf);
- if (cmp_fetch < 0) {
- if (!full_base)
- return 0;
- upstream_is_gone = 1;
-+ char *compare_branches_config = NULL;
-+ struct string_list compare_branches = STRING_LIST_INIT_DUP;
-+ struct string_list_item *item;
-+ int reported = 0;
-+ size_t i;
-+ const char *upstream_ref;
-+ const char *push_ref;
-+
+ repo_config_get_string(the_repository, "status.comparebranches",
-+ &compare_branches_config);
++ &compare_branches);
+
-+ if (compare_branches_config) {
-+ string_list_split(&compare_branches, compare_branches_config,
-+ " ", -1);
-+ string_list_remove_empty_items(&compare_branches, 0);
++ if (compare_branches) {
++ string_list_split(&branches, compare_branches, " ", -1);
++ string_list_remove_empty_items(&branches, 0);
+ } else {
-+ string_list_append(&compare_branches, "@{upstream}");
++ string_list_append(&branches, "@{upstream}");
}
- base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
- _(" (use \"git branch --unset-upstream\" to fixup)\n"));
- } else {
- format_branch_comparison(sb, !cmp_fetch, ours, theirs, base, abf, show_divergence_advice);
-+ for (i = 0; i < compare_branches.nr; i++) {
++ for (i = 0; i < branches.nr; i++) {
+ char *full_ref;
+ char *short_ref;
+ int ours, theirs, cmp;
+ int is_upstream, is_push;
+ unsigned flags = 0;
+
-+ item = &compare_branches.items[i];
-+ full_ref = resolve_compare_branch(branch, item->string);
++ full_ref = resolve_compare_branch(branch,
++ branches.items[i].string);
+ if (!full_ref)
+ continue;
+
++ if (string_list_has_string(&processed_refs, full_ref)) {
++ free(full_ref);
++ continue;
++ }
++ string_list_insert(&processed_refs, full_ref);
++
+ short_ref = refs_shorten_unambiguous_ref(
+ get_main_ref_store(the_repository), full_ref, 0);
+
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
- free(base);
- return 1;
-+ string_list_clear(&compare_branches, 0);
-+ free(compare_branches_config);
++ string_list_clear(&branches, 0);
++ string_list_clear(&processed_refs, 0);
++ free(compare_branches);
+ return reported;
}
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ )
+'
+
++test_expect_success 'status.compareBranches from upstream has no duplicates' '
++ (
++ cd test &&
++ git checkout main &&
++ git status >../actual
++ ) &&
++ cat >expect <<-EOF &&
++ On branch main
++ Your branch is up to date with ${SQ}origin/main${SQ}.
++
++ nothing to commit, working tree clean
++ EOF
++ test_cmp expect actual
++'
++
+test_expect_success 'status.compareBranches shows ahead of both upstream and push branch' '
+ (
+ cd test &&
--
gitgitgadget