git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] pull: add pull.autoStash config option

From
Junio C Hamano <gitster@pobox.com>
Date
Jul 18, 2025, 22:13 UTC
Message-ID
<xmqqjz45172n.fsf@gitster.g>
In-Reply-To
<20250718035221.2293-1-yldhome2d2@gmail.com>
Lidong Yan <yldhome2d2@gmail.com> writes:
Show 11 quoted lines
> Git uses `rebase.autostash` or `merge.autostash` to determine whether a
> dirty worktree is allowed during pull. However, this behavior is not
> clearly documented, making it difficult for users to discover how to
> enable autostash, or causing them to unknowingly enable it. Add new
> config option `pull.autostash` along with its documentation and test
> cases.
>
> `pull.autostash` provides the same functionality as `rebase.autostash`
> and `merge.autostash`, but overrides them when set. If `pull.autostash`
> is not set, it falls back to `rebase.autostash` or `merge.autostash`,
> depending on the value of `pull.rebase`.
Very well reasoned and described.
Show 22 quoted lines
> diff --git a/Documentation/config/pull.adoc b/Documentation/config/pull.adoc
> index 9349e09261..3aa1e67923 100644
> --- a/Documentation/config/pull.adoc
> +++ b/Documentation/config/pull.adoc
> @@ -13,6 +13,17 @@ pull.rebase::
>  	of merging the default branch from the default remote when "git
>  	pull" is run. See "branch.<name>.rebase" for setting this on a
>  	per-branch basis.
> +
> +pull.autoStash::
> +	When true, Git will automatically perform a `git stash` before the
> +	operation and then restore the local changes with `git stash pop`
> +	after the pull is complete. This means that you can run pull on a
> +	dirty worktree. If `pull.autostash` is set, it takes precedence over
> +	`rebase.autostash` and `merge.autostash`. If `pull.autostash` is not
> +	set, it falls back to `rebase.autostash` or `merge.autostash`,
> +	depending on the value of `pull.rebase`. This option can be
> +	overridden by the `--no-autostash` and `--autostash` options of
> +	linkgit:git-pull[1]. Defaults to false.
>  +
>  When `merges` (or just 'm'), pass the `--rebase-merges` option to 'git rebase'
>  so that the local merge commits are included in the rebase (see

The new text is inserted at a wrong spot. This "+\nWhen `merges`" is a continuation of the text that describes `pull.rebase`. If that is set to `true`, one thing happens. If that is set to `merges`, something else happens.

Insert the text for `pull.autoStash` immediately before the description of the `pull.octopus` configuration variable.

As to the text itself, "you can run pull on a dirty worktree" may not be what you want to say here, for a few reasons.

 * (pedantic) Even without the configuration variable set, you can
   run "git pull" in a dirty working tree; it just will refuse to do
   any damage until you stash the local changes away yourself.
 * If your "git pull" merges, it would work even in a dirty working
   tree as long as your local change doesn't overlap with what the
   merge would bring in.  This is quite useful for a maintainer with
   "upcoming" change to GIT-VERSION-GEN always updated locally in
   the working tree and not having to worry about pulling from
   contributors and submaintainers who won't usually be touching
   that file, for example.
 * Not limited to this instance, when you have to say "(This|It)
   means <<B>>" immediately after making a statement <<A>, I would
   like us to think if we can just say <<B>> without saying <<A> at
   all.  In this case, it is not so, which makes me suspect that
   perhaps we do not even want to say <<B>>, as it may not mean
   <<B>> after all.
Here is my attempt.
    When set to true, automatically create a temporary stash entry
    to record the local changes before the operation begins, and
    restore them after the operation completes.  When your "git
    pull" rebases (instead of merges), this may be convenient, since
    unlike merging pull that tolerates local changes that do not
    interfere with the merge, rebasing pull refuses to work with any
    local changes.
+
If `pull.autostash` is set (either to true or false),
`merge.autostash` and `rebase.autostash` are ignored.  If
`pull.autostash` is not set at all, depending on the value of
`pull.rebase`, `merge.autostash` or `rebase.autostash` is used
instead.  Can be overridden by the `--[no-]autostash` command line
option.
Show 13 quoted lines
> diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
> index 63c9a8f04b..134da2185c 100755
> --- a/t/t5520-pull.sh
> +++ b/t/t5520-pull.sh
> @@ -472,6 +472,96 @@ test_expect_success 'pull --no-autostash & merge.autostash unset' '
>  	test_pull_autostash_fail --no-autostash --no-rebase
>  '
>  
> +test_expect_success 'pull succeeds with dirty working directory and pull.autostash set' '
> +	test_config pull.autostash true &&
> +	test_pull_autostash 1 --rebase &&
> +	test_pull_autostash 2 --no-rebase
> +'
Most trivial case.  No command line override.
Show 5 quoted lines
> +test_expect_success 'pull --autostash & pull.autostash=true' '
> +	test_config pull.autostash true &&
> +	test_pull_autostash 1 --autostash --rebase &&
> +	test_pull_autostash 2 --autostash --no-rebase
> +'

Command line override specifies the same behaviour as the configuration, so we cannot learn much from this test. It still should keep working, so the test is worth having [*], but I wonder if makes sense to combine the above two into one test, i.e. set the configuration variable to true once, and then try --rebase and --no-rebase with and without --autostash (four combinations).

    [*] In this review, unless I explicitly say "this test is wrong
    and expects an incorrect result", they are not wrong, even
    though what they test may not be as interesting as others, and I
    am not suggesting its removal.  This is one of these tests.
Show 5 quoted lines
> +test_expect_success 'pull --autostash & pull.autostash=false' '
> +	test_config pull.autostash false &&
> +	test_pull_autostash 1 --autostash --rebase &&
> +	test_pull_autostash 2 --autostash --no-rebase
> +'

Configuration should be overridden by the command line option, which is a good thing to test.

Show 5 quoted lines
> +test_expect_success 'pull --autostash & pull.autostash unset' '
> +	test_unconfig pull.autostash &&
> +	test_pull_autostash 1 --autostash --rebase &&
> +	test_pull_autostash 2 --autostash --no-rebase
> +'

Another most trivial case. Shouldn't we already have an existing test for this, back from the days before pull.autostash got introduced, since the command line option has been there all along?

Show 5 quoted lines
> +test_expect_success 'pull --no-autostash & pull.autostash=true' '
> +	test_config pull.autostash true &&
> +	test_pull_autostash_fail --no-autostash --rebase &&
> +	test_pull_autostash_fail --no-autostash --no-rebase
> +'

Configuration overridden by the option, opposite of what we saw earlier, which is another good thing to test.

Show 5 quoted lines
> +test_expect_success 'pull --no-autostash & pull.autostash=false' '
> +	test_config pull.autostash false &&
> +	test_pull_autostash_fail --no-autostash --rebase &&
> +	test_pull_autostash_fail --no-autostash --no-rebase
> +'

Uninteresting test that does not tell us much; we cannot tell which between the configuration and the command line option caused us not to auto stash with this test.

Two cases that may be worth adding to this test immediately after setting pull.autostash to false are:

	test_pull_autostash_fail --rebase &&
	test_pull_autostash_fail --no-rebase &&
Show 5 quoted lines
> +test_expect_success 'pull --no-autostash & pull.autostash unset' '
> +	test_unconfig pull.autostash &&
> +	test_pull_autostash_fail --no-autostash --rebase &&
> +	test_pull_autostash_fail --no-autostash --no-rebase
> +'

Another uninteresting case that probably should be already covered by existing test, since this tests "what happens when autostash is explicitly declined from the command line when there is no configuration variable to intervene?".

Show 5 quoted lines
> +test_expect_success 'pull.autostash=true & rebase.autostash=true' '
> +	test_config pull.autostash true &&
> +	test_config rebase.autostash true &&
> +	test_pull_autostash 1 --rebase
> +'

OK. Perhaps make sure "--no-autostash --rebase" would fail while at it in the same test?

Show 5 quoted lines
> +test_expect_success 'pull.autostash=true & rebase.autostash=false' '
> +	test_config pull.autostash true &&
> +	test_config rebase.autostash false &&
> +	test_pull_autostash 1 --rebase
> +'

This is more interesting than the previous one, as we make sure that pull.* trumps rebase.* with this test. Perhaps throw --no-autostash specified on the command line into the mix?

Show 5 quoted lines
> +test_expect_success 'pull.autostash=false & rebase.autostash=true' '
> +	test_config pull.autostash false &&
> +	test_config rebase.autostash true &&
> +	test_pull_autostash_fail --rebase
> +'

Another good one. It might be intereseting to test --no-rebase and make sure it also fails? I dunno.

Show 5 quoted lines
> +test_expect_success 'pull.autostash=false & rebase.autostash=false' '
> +	test_config pull.autostash false &&
> +	test_config rebase.autostash false &&
> +	test_pull_autostash_fail --rebase
> +'
Not as interesting as others.
Show 5 quoted lines
> +test_expect_success 'pull.autostash=true & merge.autostash=true' '
> +	test_config pull.autostash true &&
> +	test_config merge.autostash true &&
> +	test_pull_autostash 2 --no-rebase
> +'

Not as interesting as others. Throw --no-autostash given on the command line into the mix as well?

Show 5 quoted lines
> +test_expect_success 'pull.autostash=true & merge.autostash=false' '
> +	test_config pull.autostash true &&
> +	test_config merge.autostash false &&
> +	test_pull_autostash 2 --no-rebase
> +'

OK. pull.*=true trumps merge.*=false. We test the other way around next. Good.

Show 11 quoted lines
> +test_expect_success 'pull.autostash=false & merge.autostash=true' '
> +	test_config pull.autostash false &&
> +	test_config merge.autostash true &&
> +	test_pull_autostash_fail --no-rebase
> +'
> +
> +test_expect_success 'pull.autostash=false & merge.autostash=false' '
> +	test_config pull.autostash false &&
> +	test_config merge.autostash false &&
> +	test_pull_autostash_fail --no-rebase
> +'

Not very interesting. Throw anothre that gives --autostash from the command line in the mix, perhaps?

>  test_expect_success 'pull.rebase' '
>  	git reset --hard before-rebase &&
>  	test_config pull.rebase true &&
Whew.

I did not spot anything majory broken (except for the location to which the new documentation paragraph goes) in the patch. Nicely done.

Thanks.
Previous: Lidong YanNext: Lidong Yan
Message 19 of 23 in “[BUG] git pull ignores pull.autostash=true configuration when used with --git-dir and --work-tree flags on a bare repository”
  1. Bryan LeeJul 15, 2025
  2. Lidong YanJul 15, 2025
  3. Bryan LeeJul 15, 2025
  4. Bryan LeeJul 15, 2025
  5. Lidong YanJul 15, 2025
  6. Junio C HamanoJul 15, 2025
  7. Lidong YanJul 16, 2025
  8. Johannes SixtJul 16, 2025
  9. Lidong YanJul 16, 2025
  10. Junio C HamanoJul 16, 2025
  11. pull: add pull.autoStash config optionLidong Yan, Jul 17, 2025
  12. Eric SunshineJul 17, 2025
  13. Lidong YanJul 17, 2025
  14. Junio C HamanoJul 17, 2025
  15. Lidong YanJul 17, 2025
  16. Junio C HamanoJul 17, 2025
  17. Junio C HamanoJul 17, 2025
  18. pull: add pull.autoStash config optionLidong Yan, Jul 18, 2025
  19. Junio C HamanoJul 18, 2025
  20. Lidong YanJul 19, 2025
  21. pull: add pull.autoStash config optionLidong Yan, Jul 20, 2025
  22. Junio C HamanoJul 21, 2025
  23. Ben KnobleJul 17, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.