[PATCH v15 0/2] status: show comparison with push remote tracking branch
From: Harald Nordgren via GitGitGadget <hidden>
Date: 2026-01-04 11:53:57
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 [off-list ref] ## 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 [off-list ref] ## 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