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

Re: stashing only unstaged changes?

From
EEErik Cervin Edin <erik@cervined.in>
Date
Jun 24, 2022, 11:23 UTC
Message-ID
<CA+JQ7M9jBSB8tdpz85imER4SF1yhn3jes8ThnzkA_O9+mus1Ng@mail.gmail.com>
In-Reply-To
<20220621142618.239b02cd@bigbox.attlocal.net>
My $0.02
On Tue, Jun 21, 2022 at 9:57 PM Tim Chase <git@tim.thechases.com> wrote:
Show 6 quoted lines
>
> I recently had composed a commit with some `git add -p` leaving some
> portions unstaged. I wanted to stash the unstaged changes to make
> sure that the staged code ran as expected, so I did  a `git stash`
> only to find that it unstaged my staged changes and stashed
> *everything*.
What you wanted to do was
  git stash --keep-index
which creates a stash with the staged and unstaged changes but leaves
the staged ones in the working tree.
If you forget to do this, what you do is try
  git stash pop --index
and then
  git stash --keep-index
> Using `git stash --saved` does the opposite of what I want (stashing
> the index, not the difference between the index and the working-copy)
I'm unaware of a --saved option

My understanding (which may be incorrect) is that a shash is always of the staged/unstaged changes and there's no way to stash only one or the other in a single stash operation.

Show 6 quoted lines
> So I carefully re-`git add -p`'ed everything and tried `git stash
> --keep-index` which sounded promising (my index remained the same),
> but popping my stash ended up causing conflicts because it had
> stashed the diff of HEAD..working-copy, not INDEX..working-copy.  A
> `git stash show -p` confirmed that the stash included things that I
> had already staged.
Such conflicts are usually trivially be resolved by taking "theirs"
I have a helper script that does this and it's basically
  git ls-files --unmerged -z |\
    xargs -0 sed -i -e '/^<\{7\}/,/^=\{7\}/d' --e '/^>\{7\}/d' &&
    git ls-files --unmerged -z | xargs -0 git add --
though, unfortunately, it also stages the content as a part of marking
resolution.
> So I carefully re-`git add -p`ed everything yet again, but then got
> stuck trying to convince `stash` to save a snapshot of only the diff
> in my working directory.
A stash is always both staged and unstaged changes of the files.
To stash only staged you may do
  git stash --keep-index
  git stash
The first stash will include staged/unstaged and the second only staged
To create a stash of only unstaged
  git commit -m tmp # create temporary commit w staged
  git stash # stash unstaged
  git reset HEAD~ &&  git stash # stash the previous staged as
unstaged (optionally git add  in the middle)
  git stash apply/pop stash@{1} # get the "unstaged" stash
As you noted such a stash is still based on a tree that may have
contained staged changes (ORIG_HEAD).
Ie. if you staged line 1 but not 2-3 the "unstaged" stash will also
contain line 1
This is doesn't happen if the staged/unstaged contain different files
Show 5 quoted lines
> To work around it, I did a `git diff >
> temp.patch` to obtain the stuff I'd wanted to stash, a `git reset
> --staged` to clear out those changes, ran my code to verify
> (eventually committing it), and then applied the `temp.patch` back on
> top of my changes. It worked, but felt convoluted.

That's basically what you have to do if you only want certain changes. (and also what --patch does under the hood)

> I did see the `git stash -p` option, to manually choose the inverse
> bits, but for what I was doing, it was more sensible to `git add -p`
> and try to stash the rest.
git stash --patch is MUCH slower than git add -p, so I personally never use it.
In my workflow I find it better to either
  git add -p
and then
  git stash --keep-index
or creating regular temporary commits, and fiddling with those,
perhaps using rebase and friends.
> So is there some option I've missed to tell `git stash` to stash only
> the delta between the uncommitted-index and the working-copy?
No, there is none.

In my experience, using regular add/commit/reset/branch/checkout/rebase is superior to using the stash for separating changes into discrete commits.

Previous: Konstantin KhomoutovNext: Tim Chase
Message 5 of 10 in “stashing only unstaged changes?”
  1. Tim ChaseJun 21, 2022
  2. RetoJun 24, 2022
  3. Tim ChaseJun 24, 2022
  4. Konstantin KhomoutovJun 24, 2022
  5. Erik Cervin EdinJun 24, 2022
  6. Tim ChaseJun 24, 2022
  7. Ævar Arnfjörð BjarmasonJun 24, 2022
  8. Erik Cervin EdinJun 24, 2022
  9. Ævar Arnfjörð BjarmasonJun 24, 2022
  10. Junio C HamanoJun 24, 2022

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.