From a2fc10f7f9d73683263c24823cfacc3a10253c7e Mon Sep 17 00:00:00 2001 From: Harald Nordgren Date: Mon, 31 Aug 2026 12:00:01 +0000 Subject: [PATCH] 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 Signed-off-by: Junio C Hamano --- builtin/checkout.c | 15 +++++++++------ sequencer.c | 3 ++- t/t7201-co.sh | 16 ++++++++++++---- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index b78b3a1d16..ce560a93d9 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -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) { diff --git a/sequencer.c b/sequencer.c index 57855b0066..240892a6d9 100644 --- a/sequencer.c +++ b/sequencer.c @@ -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) diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 7613b1d2a4..641d6239dc 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -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 &&