From: Harald Nordgren via GitGitGadget Date: Wed, 04 Mar 2026 12:25:29 GMT Subject: [PATCH v31 0/2] status: add status.compareBranches config for multiple branch comparisons Message-ID: In-Reply-To: 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 | 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