Merge branch 'hn/status-pull-advice-qualified' into seen

Advice shown by "git status" when the local branch is behind or has
diverged from its push branch has been updated to suggest "git pull
<remote> <branch>".

* hn/status-pull-advice-qualified:
  remote: qualify "git pull" advice for non-upstream compareBranches
This commit is contained in:
Junio C Hamano
2026-06-04 08:14:08 +09:00
2 changed files with 140 additions and 8 deletions

View File

@@ -2315,6 +2315,8 @@ static void format_branch_comparison(struct strbuf *sb,
bool up_to_date,
int ours, int theirs,
const char *branch_name,
const char *push_remote_name,
const char *push_branch_name,
enum ahead_behind_flags abf,
unsigned flags)
{
@@ -2350,9 +2352,15 @@ static void format_branch_comparison(struct strbuf *sb,
"and can be fast-forwarded.\n",
theirs),
branch_name, theirs);
if (use_pull_advice && advice_enabled(ADVICE_STATUS_HINTS))
strbuf_addstr(sb,
_(" (use \"git pull\" to update your local branch)\n"));
if (use_pull_advice && advice_enabled(ADVICE_STATUS_HINTS)) {
if (push_remote_name && push_branch_name)
strbuf_addf(sb,
_(" (use \"git pull %s %s\" to update your local branch)\n"),
push_remote_name, push_branch_name);
else
strbuf_addstr(sb,
_(" (use \"git pull\" to update your local branch)\n"));
}
} else {
strbuf_addf(sb,
Q_("Your branch and '%s' have diverged,\n"
@@ -2363,9 +2371,15 @@ static void format_branch_comparison(struct strbuf *sb,
"respectively.\n",
ours + theirs),
branch_name, ours, theirs);
if (use_divergence_advice && advice_enabled(ADVICE_STATUS_HINTS))
strbuf_addstr(sb,
_(" (use \"git pull\" if you want to integrate the remote branch with yours)\n"));
if (use_divergence_advice && advice_enabled(ADVICE_STATUS_HINTS)) {
if (push_remote_name && push_branch_name)
strbuf_addf(sb,
_(" (use \"git pull %s %s\" if you want to integrate the remote branch with yours)\n"),
push_remote_name, push_branch_name);
else
strbuf_addstr(sb,
_(" (use \"git pull\" if you want to integrate the remote branch with yours)\n"));
}
}
}
@@ -2403,6 +2417,8 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
int ours, theirs, cmp;
int is_upstream, is_push;
unsigned flags = 0;
const char *push_remote_name = NULL;
const char *push_branch_name = NULL;
full_ref = resolve_compare_branch(branch,
branches.items[i].string);
@@ -2446,11 +2462,27 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
if (is_upstream)
flags |= ENABLE_ADVICE_PULL;
if (is_push)
flags |= ENABLE_ADVICE_PUSH;
if (show_divergence_advice && is_upstream)
flags |= ENABLE_ADVICE_DIVERGENCE;
if (is_push) {
flags |= ENABLE_ADVICE_PUSH;
if (!upstream_ref || strcmp(upstream_ref, full_ref)) {
push_remote_name = pushremote_for_branch(branch, NULL);
if (push_remote_name &&
skip_prefix(full_ref, "refs/remotes/", &push_branch_name) &&
skip_prefix(push_branch_name, push_remote_name, &push_branch_name) &&
*push_branch_name == '/') {
push_branch_name++;
flags |= ENABLE_ADVICE_PULL;
} else {
push_remote_name = NULL;
}
} else {
flags |= ENABLE_ADVICE_PULL;
}
}
format_branch_comparison(sb, !cmp, ours, theirs, short_ref,
push_remote_name, push_branch_name,
abf, flags);
reported = 1;

View File

@@ -646,4 +646,104 @@ test_expect_success 'status.compareBranches with remapped push and upstream remo
test_cmp expect actual
'
test_expect_success 'status.compareBranches behind both upstream and push' '
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 feature13 upstream/main &&
(cd test && advance work13) &&
git -C test push origin &&
git -C test branch --set-upstream-to upstream/ahead &&
git -C test reset --hard HEAD^ &&
git -C test status >actual &&
cat >expect <<-EOF &&
On branch feature13
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 behind ${SQ}origin/feature13${SQ} by 1 commit, and can be fast-forwarded.
(use "git pull origin feature13" to update your local branch)
nothing to commit, working tree clean
EOF
test_cmp expect actual
'
test_expect_success 'status.compareBranches with remapped push and behind push branch' '
test_config -C test remote.pushDefault origin &&
test_config -C test remote.origin.push refs/heads/feature14:refs/heads/remapped14 &&
test_config -C test status.compareBranches "@{push}" &&
git -C test checkout -b feature14 upstream/main &&
(cd test && advance work14) &&
git -C test push &&
git -C test reset --hard HEAD^ &&
git -C test status >actual &&
cat >expect <<-EOF &&
On branch feature14
Your branch is behind ${SQ}origin/remapped14${SQ} by 1 commit, and can be fast-forwarded.
(use "git pull origin remapped14" to update your local branch)
nothing to commit, working tree clean
EOF
test_cmp expect actual
'
test_expect_success 'status.compareBranches with behind push branch and no upstream' '
test_config -C test push.default current &&
test_config -C test remote.pushDefault origin &&
test_config -C test status.compareBranches "@{push}" &&
git -C test checkout --no-track -b feature15 upstream/main &&
(cd test && advance work15) &&
git -C test push origin &&
git -C test reset --hard HEAD^ &&
git -C test status >actual &&
cat >expect <<-EOF &&
On branch feature15
Your branch is behind ${SQ}origin/feature15${SQ} by 1 commit, and can be fast-forwarded.
(use "git pull origin feature15" to update your local branch)
nothing to commit, working tree clean
EOF
test_cmp expect actual
'
test_expect_success 'status.compareBranches behind upstream-equals-push suggests plain pull' '
test_config -C test status.compareBranches "@{upstream} @{push}" &&
git -C test checkout -b feature16 origin/main &&
(cd test && advance work16) &&
git -C test push origin HEAD:main &&
git -C test reset --hard HEAD^ &&
git -C test status >actual &&
cat >expect <<-EOF &&
On branch feature16
Your branch is behind ${SQ}origin/main${SQ} by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
EOF
test_cmp expect actual
'
test_expect_success 'status.compareBranches suppresses advice when push tracking ref is unconventional' '
test_config -C test push.default current &&
test_config -C test remote.imported.url ../. &&
test_config -C test remote.imported.fetch "+refs/heads/*:refs/imported/imported/*" &&
test_config -C test branch.feature17.pushRemote imported &&
test_config -C test status.compareBranches "@{push}" &&
git -C test fetch imported &&
git -C test checkout --no-track -b feature17 refs/imported/imported/main &&
(cd test && advance work17) &&
git -C test push imported HEAD:feature17 &&
git -C test fetch imported &&
git -C test reset --hard HEAD^ &&
git -C test status >actual &&
cat >expect <<-EOF &&
On branch feature17
Your branch is behind ${SQ}imported/imported/feature17${SQ} by 1 commit, and can be fast-forwarded.
nothing to commit, working tree clean
EOF
test_cmp expect actual
'
test_done