checkout: print blank line after autostash conflict advice

When "git checkout -m" stashes the user's local changes and then fails
to re-apply them because of conflicts, the conflict advice is printed
directly on top of the branch-switch message ("Switched to branch ..."),
making the two messages hard to tell apart.  Print a blank line in
between when the stash apply conflicted, so that the advice and the
branch-switch message are visually distinct.

To learn whether the stash apply resulted in conflicts, make the
autostash apply functions return 1 when the stash could not be applied
due to conflicts (and was stored back), while success and error remain
0 and -1 respectively.  Checkout can then use the return value to decide
whether to print the blank line.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
jch
Harald Nordgren 2026-08-31 12:00:01 +00:00 committed by Junio C Hamano
parent e9019fcafe
commit a2fc10f7f9
3 changed files with 23 additions and 11 deletions

View File

@ -1163,6 +1163,7 @@ static int switch_branches(const struct checkout_opts *opts,
int flag, writeout_error = 0;
int do_merge = 1;
int created_autostash = 0;
int autostash_res = 0;
struct strbuf old_commit_shortname = STRBUF_INIT;
struct strbuf autostash_msg = STRBUF_INIT;
const char *stash_label_base = NULL;
@ -1234,12 +1235,12 @@ static int switch_branches(const struct checkout_opts *opts,
git_config_push_parameter(cfg.buf);
strbuf_release(&cfg);
}
apply_autostash_ref(the_repository,
"CHECKOUT_AUTOSTASH_HEAD",
new_branch_info->name,
"local",
stash_label_base,
autostash_msg.buf);
autostash_res = apply_autostash_ref(the_repository,
"CHECKOUT_AUTOSTASH_HEAD",
new_branch_info->name,
"local",
stash_label_base,
autostash_msg.buf);
}
if (ret) {
branch_info_release(&old_branch_info);
@ -1252,6 +1253,8 @@ static int switch_branches(const struct checkout_opts *opts,
if (!opts->quiet && !old_branch_info.path && old_branch_info.commit && new_branch_info->commit != old_branch_info.commit)
orphaned_commit_warning(old_branch_info.commit, new_branch_info->commit);

if (autostash_res == 1 && !opts->quiet)
fputc('\n', stderr);
update_refs_for_switch(opts, &old_branch_info, new_branch_info);

if (created_autostash) {

View File

@ -4748,7 +4748,8 @@ static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply,
if (label_base)
strvec_pushf(&child.args, "--label-base=%s", label_base);
strvec_push(&child.args, stash_oid);
ret = run_command(&child);
if (run_command(&child))
ret = 1;
}

if (attempt_apply && !ret)

View File

@ -236,10 +236,18 @@ test_expect_success 'checkout -m creates a recoverable stash on conflict' '
test_must_fail git checkout side 2>stderr &&
test_grep "Your local changes" stderr &&
git checkout -m side >actual 2>&1 &&
test_grep "resulted in conflicts" actual &&
test_grep "git stash drop" actual &&
test_grep "git stash pop" actual &&
test_grep "The following paths have local changes" actual &&
cat >expect <<-EOF &&
Your local changes are stashed, however applying them
resulted in conflicts. You can either resolve the conflicts
and then discard the stash with "git stash drop", or, if you
do not want to resolve them now, run "git reset --hard" and
apply the local changes later by running "git stash pop".

Switched to branch ${SQ}side${SQ}
The following paths have local changes:
M one
EOF
test_cmp expect actual &&
git log -p -1 --format="%gs%n%B" -g --diff-merges=1 refs/stash >actual &&
sed /^index/d actual >actual.trimmed &&
cat >expect <<-EOF &&