Re: [PATCH 2/2] checkout -m: refine autostash fallback
From: Phillip Wood <hidden>
Date: 2026-08-27 13:05:19
Hi Harald On 25/07/2026 16:34, Harald Nordgren via GitGitGadget wrote:
From: Harald Nordgren <redacted> When unpack_trees() fails under "git checkout -m", only create an autostash and retry if there are tracked local changes. Without such changes, the fallback cannot help and merely repeats the same failure.
Unfortunately to do that we have to look for local changes before the first call to unpack_trees() so we're trading an occasional inconvenience of an unnecessary stash and unstash for the cost of looking for local changes on every invocation of "git checkout -m". I don't think that is a good trade off, especially as there is no guarantee that stashing the local changes will make unpack_trees() succeed. To do this effectively would require refactoring unpack_trees() to write its error messages to a buffer and return an error flag that indicates all the errors that were encountered. We could then check if the only thing that prevented upack_trees() from succeeding was local changes to files and stash them, or if there are other errors print the error message. I suspect such a change is far from straight forward.
Use the conflict result from apply_autostash_ref() to print a blank line before the branch-switch message, visually separating it from the conflict advice.
This change is very welcome and could happily be squashed into the first patch as it motivates the changes in it.
quoted hunk ↗ jump to hunk
diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 0ddd1ad7aa..f9696dab36 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh@@ -240,6 +240,14 @@ test_expect_success 'checkout -m creates a recoverable stash on conflict' ' test_grep "git stash drop" actual && test_grep "git stash pop" actual && test_grep "The following paths have local changes" actual && + sed -n "/apply the local changes later/,/Switched to branch/p" \ + actual >separator.actual && + cat >separator.expect <<-EOF && + apply the local changes later by running "git stash pop". + + Switched to branch ${SQ}side${SQ} + EOF + test_cmp separator.expect separator.actual &&
I wonder whether we should just bite the bullet and check what gets printed to the screen with test_cmp, rather than grepping for all these separate parts of the message. Is there something in the message that makes that difficult? Thanks Phillip
quoted hunk ↗ jump to hunk
git log -p -1 --format="%gs%n%B" -g --diff-merges=1 refs/stash >actual && sed /^index/d actual >actual.trimmed && cat >expect <<-EOF &&@@ -262,11 +270,18 @@ test_expect_success 'checkout -m creates a recoverable stash on conflict' ' git reset --hard ' -test_expect_success 'checkout -m which would overwrite untracked file' ' +test_expect_success 'checkout -m only retries untracked-file failure with local changes' ' git checkout -f --detach main && test_commit another-file && git checkout HEAD^ && >another-file.t && + test_must_fail env GIT_TRACE2_EVENT="$(pwd)/trace" \ + git checkout -m @{-1} 2>err && + test_grep "untracked working tree files" err && + grep "\"region_enter\".*\"category\":\"index\",\"label\":\"refresh\"" \ + trace >refresh.events && + test_line_count = 1 refresh.events && + fill 1 2 3 4 5 >one && test_must_fail git checkout -m @{-1} 2>err && q_to_tab >expect <<-\EOF &&