[PATCH v15 0/2] status: show comparison with push remote tracking branch
- From
Harald Nordgren via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Jan 4, 2026, 11:53 UTC
- Message-ID
- <pull.2138.v15.git.git.1767527634.gitgitgadget@gmail.com>
- In-Reply-To
- <pull.2138.v14.git.git.1767445236.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
Harald Nordgren (2): refactor format_branch_comparison in preparation status: show comparison with push remote tracking branch
remote.c | 168 ++++++++++++++++++++++++------- t/t6040-tracking-info.sh | 210 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 342 insertions(+), 36 deletions(-)
base-commit: 68cb7f9e92a5d8e9824f5b52ac3d0a9d8f653dbe Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2138%2FHaraldNordgren%2Fahead_of_main_status-v15 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2138/HaraldNordgren/ahead_of_main_status-v15 Pull-Request: https://github.com/git/git/pull/2138
Range-diff vs v14:
1: a2c160c53e ! 1: cf4e9779c5 refactor: format_branch_comparison in preparation
@@ Metadata
Author: Harald Nordgren <haraldnordgren@gmail.com>
## Commit message ##
- refactor: format_branch_comparison in preparation
+ refactor format_branch_comparison in preparation
Refactor format_branch_comparison function in preparation for showing
comparison with push remote tracking branch.
@@ remote.c: int stat_tracking_info(struct branch *branch, int *num_ours, int *num_
- enum ahead_behind_flags abf,
- int show_divergence_advice)
+static void format_branch_comparison(struct strbuf *sb,
-+ int ahead, int behind,
++ int ours, int theirs,
+ const char *branch_name,
-+ int upstream_is_gone,
+ enum ahead_behind_flags abf,
-+ int sti)
++ int show_divergence_advice)
{
- int ours, theirs, sti;
- const char *full_base;
@@ remote.c: int stat_tracking_info(struct branch *branch, int *num_ours, int *num_
-
- base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
- full_base, 0);
- if (upstream_is_gone) {
- strbuf_addf(sb,
- _("Your branch is based on '%s', but the upstream is gone.\n"),
+- if (upstream_is_gone) {
+- strbuf_addf(sb,
+- _("Your branch is based on '%s', but the upstream is gone.\n"),
- base);
-+ branch_name);
- if (advice_enabled(ADVICE_STATUS_HINTS))
- strbuf_addstr(sb,
- _(" (use \"git branch --unset-upstream\" to fixup)\n"));
- } else if (!sti) {
- strbuf_addf(sb,
- _("Your branch is up to date with '%s'.\n"),
+- if (advice_enabled(ADVICE_STATUS_HINTS))
+- strbuf_addstr(sb,
+- _(" (use \"git branch --unset-upstream\" to fixup)\n"));
+- } else if (!sti) {
+- strbuf_addf(sb,
+- _("Your branch is up to date with '%s'.\n"),
- base);
-+ branch_name);
- } else if (abf == AHEAD_BEHIND_QUICK) {
+- } else if (abf == AHEAD_BEHIND_QUICK) {
++ if (abf == AHEAD_BEHIND_QUICK) {
strbuf_addf(sb,
_("Your branch and '%s' refer to different commits.\n"),
- base);
@@ remote.c: int stat_tracking_info(struct branch *branch, int *num_ours, int *num_
if (advice_enabled(ADVICE_STATUS_HINTS))
strbuf_addf(sb, _(" (use \"%s\" for details)\n"),
"git status --ahead-behind");
-- } else if (!theirs) {
-+ } else if (ahead == 0 && behind == 0) {
++ } else if (!ours && !theirs) {
+ strbuf_addf(sb,
+ _("Your branch is up to date with '%s'.\n"),
+ branch_name);
-+ } else if (ahead > 0 && behind == 0) {
+ } else if (!theirs) {
strbuf_addf(sb,
Q_("Your branch is ahead of '%s' by %d commit.\n",
"Your branch is ahead of '%s' by %d commits.\n",
-- ours),
+ ours),
- base, ours);
-- if (advice_enabled(ADVICE_STATUS_HINTS))
-- strbuf_addstr(sb,
-- _(" (use \"git push\" to publish your local commits)\n"));
-- } else if (!ours) {
-+ ahead),
-+ branch_name, ahead);
-+ } else if (behind > 0 && ahead == 0) {
- strbuf_addf(sb,
- Q_("Your branch is behind '%s' by %d commit, "
- "and can be fast-forwarded.\n",
++ branch_name, ours);
+ if (advice_enabled(ADVICE_STATUS_HINTS))
+ strbuf_addstr(sb,
+ _(" (use \"git push\" to publish your local commits)\n"));
+@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
"Your branch is behind '%s' by %d commits, "
"and can be fast-forwarded.\n",
-- theirs),
+ theirs),
- base, theirs);
-- if (advice_enabled(ADVICE_STATUS_HINTS))
-- strbuf_addstr(sb,
-- _(" (use \"git pull\" to update your local branch)\n"));
-- } else {
-+ behind),
-+ branch_name, behind);
-+ } else if (ahead > 0 && behind > 0) {
- strbuf_addf(sb,
- Q_("Your branch and '%s' have diverged,\n"
- "and have %d and %d different commit each, "
++ branch_name, theirs);
+ if (advice_enabled(ADVICE_STATUS_HINTS))
+ strbuf_addstr(sb,
+ _(" (use \"git pull\" to update your local branch)\n"));
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
- "Your branch and '%s' have diverged,\n"
"and have %d and %d different commits each, "
"respectively.\n",
-- ours + theirs),
+ ours + theirs),
- base, ours, theirs);
-- if (show_divergence_advice &&
-- advice_enabled(ADVICE_STATUS_HINTS))
-+ ahead + behind),
-+ branch_name, ahead, behind);
-+ }
++ branch_name, ours, theirs);
+ if (show_divergence_advice &&
+ advice_enabled(ADVICE_STATUS_HINTS))
+ strbuf_addstr(sb,
+ _(" (use \"git pull\" if you want to integrate the remote branch with yours)\n"));
+ }
+}
+
+/*
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
+ base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ full_base, 0);
+
-+ format_branch_comparison(sb, ours, theirs, base, upstream_is_gone, abf, sti);
-+ if (sti > 0 && abf != AHEAD_BEHIND_QUICK) {
-+ if (!theirs && advice_enabled(ADVICE_STATUS_HINTS)) {
-+ strbuf_addstr(sb,
-+ _(" (use \"git push\" to publish your local commits)\n"));
-+ } else if (!ours && advice_enabled(ADVICE_STATUS_HINTS)) {
++ if (upstream_is_gone) {
++ strbuf_addf(sb,
++ _("Your branch is based on '%s', but the upstream is gone.\n"),
++ base);
++ if (advice_enabled(ADVICE_STATUS_HINTS))
+ strbuf_addstr(sb,
-+ _(" (use \"git pull\" to update your local branch)\n"));
-+ } else if (ours && theirs && show_divergence_advice &&
-+ advice_enabled(ADVICE_STATUS_HINTS)) {
- strbuf_addstr(sb,
- _(" (use \"git pull\" if you want to integrate the remote branch with yours)\n"));
-+ }
- }
++ _(" (use \"git branch --unset-upstream\" to fixup)\n"));
++ } else {
++ format_branch_comparison(sb, ours, theirs, base, abf, show_divergence_advice);
++ }
+
free(base);
return 1;
2: b9b2f15498 ! 2: a435cf4ce4 status: show comparison with push remote tracking branch
@@ Commit message
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
## remote.c ##
+@@
+
+ enum map_direction { FROM_SRC, FROM_DST };
+
++enum branch_type {
++ PUSH = 1 << 0,
++ PULL = 1 << 1
++};
++
+ struct counted_string {
+ size_t len;
+ const char *s;
@@ 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 stat_tracking_info(struct branch *branch, int *num_ours, int *num_
+}
+
static void format_branch_comparison(struct strbuf *sb,
- int ahead, int behind,
+ int ours, int theirs,
const char *branch_name,
+ enum ahead_behind_flags abf,
++ enum branch_type bt,
+ int show_divergence_advice)
+ {
+ if (abf == AHEAD_BEHIND_QUICK) {
+@@ remote.c: static void format_branch_comparison(struct strbuf *sb,
+ "Your branch is ahead of '%s' by %d commits.\n",
+ ours),
+ branch_name, ours);
+- if (advice_enabled(ADVICE_STATUS_HINTS))
++ if ((bt & PUSH) && advice_enabled(ADVICE_STATUS_HINTS))
+ strbuf_addstr(sb,
+ _(" (use \"git push\" to publish your local commits)\n"));
+ } else if (!ours) {
+@@ remote.c: static void format_branch_comparison(struct strbuf *sb,
+ "and can be fast-forwarded.\n",
+ theirs),
+ branch_name, theirs);
+- if (advice_enabled(ADVICE_STATUS_HINTS))
++ if ((bt & PULL) && advice_enabled(ADVICE_STATUS_HINTS))
+ strbuf_addstr(sb,
+ _(" (use \"git pull\" to update your local branch)\n"));
+ } else {
+@@ remote.c: static void format_branch_comparison(struct strbuf *sb,
+ "respectively.\n",
+ ours + theirs),
+ branch_name, ours, theirs);
+- if (show_divergence_advice &&
++ if ((bt & PULL) &&
++ show_divergence_advice &&
+ advice_enabled(ADVICE_STATUS_HINTS))
+ strbuf_addstr(sb,
+ _(" (use \"git pull\" if you want to integrate the remote branch with yours)\n"));
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
const char *full_base;
char *base;
int upstream_is_gone = 0;
++ enum branch_type base_bt = PUSH | PULL;
+ int push_ours, push_theirs, push_sti;
+ char *full_push = NULL;
+ char *push = NULL;
-+ int show_push_comparison = 0;
++ enum branch_type push_bt = 0;
sti = stat_tracking_info(branch, &ours, &theirs, &full_base, 0, abf);
if (sti < 0) {
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
+ if (push && strcmp(base, push)) {
+ push_sti = stat_branch_pair(branch->refname, full_push,
+ &push_ours, &push_theirs, abf);
-+ if (push_sti >= 0)
-+ show_push_comparison = 1;
++ if (push_sti >= 0) {
++ base_bt = PULL;
++ push_bt = PUSH;
++ }
+ }
+
- format_branch_comparison(sb, ours, theirs, base, upstream_is_gone, abf, sti);
- if (sti > 0 && abf != AHEAD_BEHIND_QUICK) {
-- if (!theirs && advice_enabled(ADVICE_STATUS_HINTS)) {
-+ if (!theirs && !show_push_comparison &&
-+ advice_enabled(ADVICE_STATUS_HINTS)) {
- strbuf_addstr(sb,
- _(" (use \"git push\" to publish your local commits)\n"));
- } else if (!ours && advice_enabled(ADVICE_STATUS_HINTS)) {
+ if (upstream_is_gone) {
+ strbuf_addf(sb,
+ _("Your branch is based on '%s', but the upstream is gone.\n"),
@@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,
- }
- }
-
-+ if (show_push_comparison) {
-+ strbuf_addstr(sb, "\n");
-+ format_branch_comparison(sb, push_ours, push_theirs, push, 0, abf, push_sti);
-+ if (push_sti > 0 && abf != AHEAD_BEHIND_QUICK) {
-+ if (!push_theirs && advice_enabled(ADVICE_STATUS_HINTS)) {
-+ strbuf_addstr(sb,
-+ _(" (use \"git push\" to publish your local commits)\n"));
-+ }
-+ }
+ strbuf_addstr(sb,
+ _(" (use \"git branch --unset-upstream\" to fixup)\n"));
+ } else {
+- format_branch_comparison(sb, ours, theirs, base, abf, show_divergence_advice);
++ format_branch_comparison(sb, ours, theirs, base, abf, base_bt,
++ show_divergence_advice);
+ }
+
++ if (push_bt & PUSH) {
++ strbuf_addstr(sb, "\n");
++ format_branch_comparison(sb, push_ours, push_theirs, push, abf,
++ push_bt, 0);
+ }
+
free(base);
+ free(full_push);
+ free(push);-- gitgitgadget