Git development
 help / color / mirror / Atom feed
From: Phillip Wood <phillip.wood123@gmail.com>
To: jasmeet.bhatia.us@gmail.com, git@vger.kernel.org
Cc: Deveshi Dwivedi <deveshigurgaon@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Patrick Steinhardt <ps@pks.im>,
	Leon Michalak <leonmichalak6@gmail.com>
Subject: Re: [PATCH] stash: reuse prepared state when creating stash
Date: Mon, 2 Nov 2026 14:14:57 +0000	[thread overview]
Message-ID: <845be1de-8d12-41c9-996d-038886bde4cf@gmail.com> (raw)
In-Reply-To: <20261031200107.285168-1-jasmeet.bhatia.us@gmail.com>

Hi Jasmeet

On 31/10/2026 20:01, jasmeet.bhatia.us@gmail.com wrote:
> From: "Jasmeet (Jazz) Bhatia" <jasmeet.bhatia.us@gmail.com>
> 
> do_push_stash() already preloads and refreshes the index and calls
> check_changes() before invoking do_create_stash(). However, Git then
> repeats this same index preparation and change detection, including
> rebuilding the list of untracked files when requested, which is
> duplicate work.

Good observation

> Instead, avoid this duplicate work by passing the already prepared
> untracked file list to do_create_stash(). When the list is provided,
> reuse it and skip the redundant index preload, refresh, and
> check_changes() call.

I've got some patches in "seen" [1] that take a slightly different 
approach and keep the call to check_changes() in do_create_stash() and 
remove it from create_stash() and do_push_stash() instead. That series 
also removes a number of unnecessary calls to preload_index(). If you 
have time to post a review that would be really helpful.

Thanks

Phillip

[1] The patches are at 
https://lore.kernel.org/git/cover.1792767794.git.phillip.wood@dunelm.org.uk/ 
and are merged into seen as branch 'pw/stash-change-check-only-once'


> This maintains the existing behavior of "git stash create", which
> invokes do_create_stash() without prepared state and thus continues
> to perform its own index preparation and change detection.
> 
> Testing this using the p3904 stash performance tests shows a decent
> performance boost.
> 
>      stash -p, no fsmonitor
>      0.12(0.11+0.17) -> 0.10(0.10+0.18)  -16.7%
> 
>      stash -p, builtin fsmonitor
>      0.11(0.10+0.02) -> 0.09(0.08+0.01)  -18.2%
> 
> Testing this on the Linux kernel on my system, "git stash push"
> improved from 254 ms to about 239 ms, which is about 6%.
> 
> Signed-off-by: Jasmeet (Jazz) Bhatia <jasmeet.bhatia.us@gmail.com>
> ---
>   builtin/stash.c | 25 +++++++++++++++----------
>   1 file changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/builtin/stash.c b/builtin/stash.c
> index e1a3a76bd0..58eb782597 100644
> --- a/builtin/stash.c
> +++ b/builtin/stash.c
> @@ -1459,7 +1459,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
>   			   int include_untracked, int patch_mode,
>   			   struct interactive_options *interactive_opts,
>   			   int only_staged, struct stash_info *info, struct strbuf *patch,
> -			   int quiet)
> +			   int quiet, struct strbuf *prepared_untracked_files)
>   {
>   	int ret = 0;
>   	int flags = 0;
> @@ -1473,14 +1473,17 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
>   	struct strbuf msg = STRBUF_INIT;
>   	struct strbuf commit_tree_label = STRBUF_INIT;
>   	struct strbuf untracked_files = STRBUF_INIT;
> +	struct strbuf *untracked_files_p = prepared_untracked_files ? prepared_untracked_files : &untracked_files;
>   
>   	prepare_fallback_ident("git stash", "git@stash");
>   
> -	repo_read_index_preload(the_repository, NULL, 0);
> -	if (repo_refresh_and_write_index(the_repository, REFRESH_QUIET, 0, 0,
> -					 NULL, NULL, NULL) < 0) {
> -		ret = error(_("could not write index"));
> -		goto done;
> +	if (!prepared_untracked_files) {
> +		repo_read_index_preload(the_repository, NULL, 0);
> +		if (repo_refresh_and_write_index(the_repository, REFRESH_QUIET, 0, 0,
> +						 NULL, NULL, NULL) < 0) {
> +			ret = error(_("could not write index"));
> +			goto done;
> +		}
>   	}
>   
>   	if (repo_get_oid(the_repository, "HEAD", &info->b_commit)) {
> @@ -1493,7 +1496,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
>   		head_commit = lookup_commit(the_repository, &info->b_commit);
>   	}
>   
> -	if (!check_changes(ps, include_untracked, &untracked_files)) {
> +	if (!prepared_untracked_files &&
> +	    !check_changes(ps, include_untracked, untracked_files_p)) {
>   		ret = 1;
>   		goto done;
>   	}
> @@ -1529,7 +1533,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
>   	parents = NULL;
>   
>   	if (include_untracked) {
> -		if (save_untracked_files(info, &msg, &untracked_files)) {
> +		if (save_untracked_files(info, &msg, untracked_files_p)) {
>   			if (!quiet)
>   				fprintf_ln(stderr, _("Cannot save "
>   						     "the untracked files"));
> @@ -1615,7 +1619,7 @@ static int create_stash(int argc, const char **argv, const char *prefix UNUSED,
>   		return 0;
>   
>   	ret = do_create_stash(&ps, &stash_msg_buf, 0, 0, NULL, 0, &info,
> -			      NULL, 0);
> +			      NULL, 0, NULL);
>   	if (!ret)
>   		printf_ln("%s", oid_to_hex(&info.w_commit));
>   
> @@ -1698,7 +1702,8 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
>   	if (stash_msg)
>   		strbuf_addstr(&stash_msg_buf, stash_msg);
>   	if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode,
> -			    interactive_opts, only_staged, &info, &patch, quiet)) {
> +			    interactive_opts, only_staged, &info, &patch, quiet,
> +			    &untracked_files)) {
>   		ret = -1;
>   		goto done;
>   	}


  reply	other threads:[~2026-11-02 14:15 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-31 20:01 [PATCH] stash: reuse prepared state when creating stash jasmeet.bhatia.us
2026-11-02 14:14 ` Phillip Wood [this message]
2026-11-09  5:09   ` jasmeet.bhatia.us

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=845be1de-8d12-41c9-996d-038886bde4cf@gmail.com \
    --to=phillip.wood123@gmail.com \
    --cc=deveshigurgaon@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jasmeet.bhatia.us@gmail.com \
    --cc=leonmichalak6@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox