[PATCH v31 0/2] status: add status.compareBranches config for multiple branch comparisons
- From
Harald Nordgren via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Mar 4, 2026, 12:25 UTC
- Message-ID
- <pull.2138.v31.git.git.1772627131.gitgitgadget@gmail.com>
- In-Reply-To
- <pull.2138.v30.git.git.1772102022.gitgitgadget@gmail.com>
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
comparisonsDocumentation/config/status.adoc | 25 +++ remote.c | 178 ++++++++++++---- t/t6040-tracking-info.sh | 354 +++++++++++++++++++++++++++++++ 3 files changed, 520 insertions(+), 37 deletions(-)
base-commit: 50d063e335afd5828fbb9de2f2b2fb44fd884d2b Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2138%2FHaraldNordgren%2Fahead_of_main_status-v31 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2138/HaraldNordgren/ahead_of_main_status-v31 Pull-Request: https://github.com/git/git/pull/2138
Range-diff vs v30:
1: 7f517b8c7f = 1: 320c1ce55a refactor format_branch_comparison in preparation
2: 501bd40294 ! 2: f07ccb278c status: add status.compareBranches config for multiple branch comparisons
@@ Documentation/config/status.adoc: status.aheadBehind::
+If not set, the default behavior is equivalent to `@{upstream}`, which
+compares against the configured upstream tracking branch.
++
++The entries are shown in the order they appear in the configuration.
++Duplicate entries that resolve to the same ref are suppressed after
++their first occurrence, so `@{push} @{upstream} @{push}` shows at
++most two comparisons. When `@{upstream}` and `@{push}` resolve to
++the same remote-tracking branch, only one comparison is shown.
+++
+Example:
++
+----
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
'
+test_expect_success 'status tracking origin/main shows only main' '
-+ (
-+ cd test &&
-+ git checkout b4 &&
-+ git status >../actual
-+ ) &&
++ git -C test checkout b4 &&
++ git -C test status >actual &&
+ cat >expect <<-EOF &&
+ On branch b4
+ Your branch is ahead of ${SQ}origin/main${SQ} by 2 commits.
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+'
+
+test_expect_success 'status --no-ahead-behind tracking origin/main shows only main' '
-+ (
-+ cd test &&
-+ git checkout b4 &&
-+ git status --no-ahead-behind >../actual
-+ ) &&
++ git -C test checkout b4 &&
++ git -C test status --no-ahead-behind >actual &&
+ cat >expect <<-EOF &&
+ On branch b4
+ Your branch and ${SQ}origin/main${SQ} refer to different commits.
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ test_cmp expect actual
+'
+
-+test_expect_success 'status.compareBranches from upstream has no duplicates' '
++test_expect_success 'status.compareBranches deduplicates when upstream and push are the same' '
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
+ git -C test checkout main &&
+ git -C test status >actual &&
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ test_cmp expect actual
+'
+
-+test_expect_success 'status.compareBranches shows ahead of both upstream and push branch' '
++test_expect_success 'status.compareBranches with only upstream shows only upstream' '
++ test_config -C test status.compareBranches "@{upstream}" &&
++ git -C test checkout main &&
++ git -C test 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 with only push shows only push' '
+ test_config -C test push.default current &&
-+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
++ test_config -C test status.compareBranches "@{push}" &&
+ git -C test checkout -b feature2 origin/main &&
+ git -C test push origin HEAD &&
+ (cd test && advance work) &&
+ git -C test status >actual &&
+ cat >expect <<-EOF &&
+ On branch feature2
++ Your branch is ahead of ${SQ}origin/feature2${SQ} by 1 commit.
++ (use "git push" to publish your local commits)
++
++ nothing to commit, working tree clean
++ EOF
++ test_cmp expect actual
++'
++
++test_expect_success 'status.compareBranches shows ahead of both upstream and push branch' '
++ test_config -C test push.default current &&
++ test_config -C test status.compareBranches "@{upstream} @{push}" &&
++ git -C test checkout -b feature3 origin/main &&
++ git -C test push origin HEAD &&
++ (cd test && advance work) &&
++ git -C test status >actual &&
++ cat >expect <<-EOF &&
++ On branch feature3
+ Your branch is ahead of ${SQ}origin/main${SQ} by 1 commit.
+
-+ Your branch is ahead of ${SQ}origin/feature2${SQ} by 1 commit.
++ Your branch is ahead of ${SQ}origin/feature3${SQ} by 1 commit.
+ (use "git push" to publish your local commits)
+
+ nothing to commit, working tree clean
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+test_expect_success 'checkout with status.compareBranches shows both branches' '
+ test_config -C test push.default current &&
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
-+ git -C test checkout feature2 >actual &&
++ git -C test checkout feature3 >actual &&
+ cat >expect <<-EOF &&
+ Your branch is ahead of ${SQ}origin/main${SQ} by 1 commit.
+
-+ Your branch is ahead of ${SQ}origin/feature2${SQ} by 1 commit.
++ Your branch is ahead of ${SQ}origin/feature3${SQ} by 1 commit.
+ (use "git push" to publish your local commits)
+ EOF
+ test_cmp expect actual
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ test_cmp expect actual
+'
+
++test_expect_success 'status.compareBranches deduplicates repeated specifiers' '
++ test_config -C test push.default current &&
++ test_config -C test remote.pushDefault origin &&
++ test_config -C test status.compareBranches "@{push} @{upstream} @{push}" &&
++ git -C test checkout -b feature7 upstream/main &&
++ git -C test push origin &&
++ (cd test && advance work) &&
++ git -C test status >actual &&
++ cat >expect <<-EOF &&
++ On branch feature7
++ Your branch is ahead of ${SQ}origin/feature7${SQ} by 1 commit.
++ (use "git push" to publish your local commits)
++
++ Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
++
++ nothing to commit, working tree clean
++ EOF
++ test_cmp expect actual
++'
++
+test_expect_success 'status.compareBranches with diverged push branch' '
+ test_config -C test push.default current &&
+ test_config -C test remote.pushDefault origin &&
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
-+ git -C test checkout -b feature7 upstream/main &&
-+ (cd test && advance work71) &&
++ git -C test checkout -b feature8 upstream/main &&
++ (cd test && advance work81) &&
+ git -C test push origin &&
+ git -C test reset --hard upstream/main &&
-+ (cd test && advance work72) &&
++ (cd test && advance work82) &&
+ git -C test status >actual &&
+ cat >expect <<-EOF &&
-+ On branch feature7
++ On branch feature8
+ Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
+
-+ Your branch and ${SQ}origin/feature7${SQ} have diverged,
++ Your branch and ${SQ}origin/feature8${SQ} have diverged,
+ and have 1 and 1 different commits each, respectively.
+
+ nothing to commit, working tree clean
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ test_config -C test push.default current &&
+ test_config -C test remote.pushDefault origin &&
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
-+ git -C test checkout -b feature8 upstream/main &&
++ git -C test checkout -b feature9 upstream/main &&
+ git -C test push origin &&
+ git -C test status >actual &&
+ cat >expect <<-EOF &&
-+ On branch feature8
++ On branch feature9
+ Your branch is up to date with ${SQ}upstream/main${SQ}.
+
-+ Your branch is up to date with ${SQ}origin/feature8${SQ}.
++ Your branch is up to date with ${SQ}origin/feature9${SQ}.
+
+ nothing to commit, working tree clean
+ EOF
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ test_config -C test push.default current &&
+ test_config -C test remote.pushDefault origin &&
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
-+ git -C test checkout feature8 >actual &&
++ git -C test checkout feature9 >actual &&
+ git -C test push origin &&
+ git -C test status --no-ahead-behind >actual &&
+ cat >expect <<-EOF &&
-+ On branch feature8
++ On branch feature9
+ Your branch is up to date with ${SQ}upstream/main${SQ}.
+
-+ Your branch is up to date with ${SQ}origin/feature8${SQ}.
++ Your branch is up to date with ${SQ}origin/feature9${SQ}.
+
+ nothing to commit, working tree clean
+ EOF
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ test_config -C test push.default current &&
+ test_config -C test remote.pushDefault origin &&
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
-+ git -C test checkout feature8 >actual &&
++ git -C test checkout feature9 >actual &&
+ cat >expect <<-EOF &&
+ Your branch is up to date with ${SQ}upstream/main${SQ}.
+
-+ Your branch is up to date with ${SQ}origin/feature8${SQ}.
++ Your branch is up to date with ${SQ}origin/feature9${SQ}.
+ EOF
+ test_cmp expect actual
+'
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+ git -C test checkout -b ahead upstream/main &&
+ (cd test && advance work) &&
+ git -C test push upstream HEAD &&
-+ git -C test checkout -b feature9 upstream/main &&
++ git -C test checkout -b feature10 upstream/main &&
+ git -C test push origin &&
+ git -C test branch --set-upstream-to upstream/ahead &&
+ git -C test status >actual &&
+ cat >expect <<-EOF &&
-+ On branch feature9
++ On branch feature10
+ Your branch is behind ${SQ}upstream/ahead${SQ} by 1 commit, and can be fast-forwarded.
+ (use "git pull" to update your local branch)
+
-+ Your branch is up to date with ${SQ}origin/feature9${SQ}.
++ Your branch is up to date with ${SQ}origin/feature10${SQ}.
+
+ nothing to commit, working tree clean
+ EOF
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+'
+
+test_expect_success 'status.compareBranches with remapped push refspec' '
-+ test_config -C test remote.origin.push refs/heads/feature10:refs/heads/remapped &&
++ test_config -C test remote.origin.push refs/heads/feature11:refs/heads/remapped &&
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
-+ git -C test checkout -b feature10 origin/main &&
++ git -C test checkout -b feature11 origin/main &&
+ git -C test push &&
+ (cd test && advance work) &&
+ git -C test status >actual &&
+ cat >expect <<-EOF &&
-+ On branch feature10
++ On branch feature11
+ Your branch is ahead of ${SQ}origin/main${SQ} by 1 commit.
+
+ Your branch is ahead of ${SQ}origin/remapped${SQ} by 1 commit.
@@ t/t6040-tracking-info.sh: test_expect_success '--set-upstream-to @{-1}' '
+
+test_expect_success 'status.compareBranches with remapped push and upstream remote' '
+ test_config -C test remote.pushDefault origin &&
-+ test_config -C test remote.origin.push refs/heads/feature11:refs/heads/remapped &&
++ test_config -C test remote.origin.push refs/heads/feature12:refs/heads/remapped &&
+ test_config -C test status.compareBranches "@{upstream} @{push}" &&
-+ git -C test checkout -b feature11 upstream/main &&
++ git -C test checkout -b feature12 upstream/main &&
+ git -C test push origin &&
+ (cd test && advance work) &&
+ git -C test status >actual &&
+ cat >expect <<-EOF &&
-+ On branch feature11
++ On branch feature12
+ Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
+
+ Your branch is ahead of ${SQ}origin/remapped${SQ} by 1 commit.-- gitgitgadget