I was working on a large set of changes to a code base. Some of the changes had been staged, and some had not. I needed to switch to a different branch, but was not ready to make a commit, so I stashed my current state using git stash
.
Later, I went to apply my stash with, git stash apply
. Then I ran git status
. I noticed that my staged changes no longer appeared as 'staged', and instead appear to be included as 'Changes not staged for commit'. Am I correct in my understanding that no data was actually lost, but instead 'staged' data is now simply converted to 'unstaged' data?
EDIT: I should add that some of the files in question had staged versions, and unstaged versions at the time of the stash. For example, file A had some changes made, which were staged. Then, some more changes were made to file A, which had not yet been staged. Then, a stash was made.
Stashing untracked or ignored filesBy default, running git stash will stash: changes that have been added to your index (staged changes) changes made to files that are currently tracked by Git (unstaged changes)
By default, git stash will stash only modified and staged tracked files. If you specify --include-untracked or -u , Git will include untracked files in the stash being created.
Stash only the changes that are currently staged. This is similar to basic git commit except the state is committed to the stash instead of current branch. And git will ask you for each change in your files to add or not into stash. Now you can stage your files and then run git stash-staged .
In order to stash untracked files, add the “–include-untracked” option to your “git stash” initial command. Alternatively, you can simply use the “-u” which is equivalent to the untracked longer version.
The answer to the question as asked ("does stash convert staged files to unstaged") is both yes and no.
If you've applied with git stash apply
(vs git stash pop
), you're in great shape because the stash is still present. But let's back up a bit and look at the underlying mechanism, since it matters here.
When you run git stash save
(or plain git stash
which does a save
), git makes two1 commits that are not on any branch. One commit holds the state of the index, i.e., whatever you've staged. The second commit holds state of the work tree, i.e., everything else.
Later, when you use git stash apply
, git smushes the changes together so that nothing is staged, unless you add --index
2 to the apply
operation, in which case it restores (if it can) your previous arrangement of staged vs unstaged.
When you use apply
, the stash script keeps the stash commits around as well, so if the apply does not go the way you wanted—including if you forgot --index
or misspelled it (see footnote 2)—you can git reset --hard
(assuming you had everything in a clean state when you started, anyway) and re-do the apply
.
If you've used pop
, though, and git thinks the apply worked, it then drops the stash. I generally recommend using separate apply and drop just for this reason.
1With -u
or -a
, which save not just staged and unstaged files abut also ignored and/or all files, the stash script makes three commits. Without these flags, such files don't go in to either part of the stash, though.
2Confusingly, the stash script also has a --keep-index
flag, which it allows you to specify for apply
operations but has no meaning there. Instead, --keep-index
affects what stash
does after making its special stash commits. Occasionally I've accidentally done git stash apply --keep-index
instead of git stash apply --index
, having mixed up the two options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With