For clarity:
$ git stash; git stash -u
This is two separate git stash
commands. Each one does a git stash save
since there is no more-specific verb at the end.
The first git stash
saved away both your current index and your current work-tree (by making two separate commits, neither of which is on a branch). After that, your index matched the HEAD
commit and your work-tree was clean, except of course for untracked files.
Normally, if you then tried to repeat git stash save
, it would just tell you that there was nothing to save, and would do nothing, but for your second save
you added the -u
flag: save (and then remove) untracked files. So this made a second stash, using your current index—which the first save
made equal to the HEAD
commit—and your current work tree—which, again, is equal to the HEAD
commit—and using a third commit as part of the stash-bag: the u
commit. See the drawing in this answer, but note that you have two separate stash bags hanging off the same (HEAD
) commit, in your particular case.
When you save a stash with some active stash(es), the stash
script uses git's "reflogs" to "push" the current stash into the "stash stack", making the new stash the top-most one, stash@{0}
. So your stash-bag with the u
commit in it is, at this point, stash@{0}
, while your stash with the modified-index-and/or-work-tree (and no u
commit containing untracked files) is in stash@{1}
.
You then did:
git checkout feature
or similar to change HEAD
to point to a different branch. Let's draw the situation now, by assuming that the stash was done on a branch named X
:
... - o - o - o <-- HEAD=feature
\
o - * <-- X
|\
| \
|\ \
i-w \ <-- stash@{1}
|\
i-w <-- stash@{0}
/
u
Again, both stash-bags hang off commit *
; the one in stash@{1}
has the untracked files, but its i
and w
commits are identical to commit *
itself.
You said:
using git stash show stash@{0}
and git stash show stash@{1}
, it did not show me anything for the 0th stash index and the 1st stash index showed the untracked files ...
This seems unlikely. However, if you wrote git show stash@{0}
instead of git stash show stash@{0}
, and git show stash@{1}
instead of git stash show stash@{1}
, this is what you would have seen, because git show
shows merge commits as "combined diffs", and you were basically asking git show
to look at the w
commit in each stash-bag. Each w
commit is a merge commit, it's just not the usual kind of merge, so git show
produces largely-useless results.
I went ahead and did git stash apply and that only brought back the untracked file changes, not the modified files.
That is what would be expected: git stash apply
(which applies stash@{1}
) tells git stash
to compare the work-tree and index commits (w
and i
) to their parent (commit *
), and in the case of a three-parent stash-bag, to extract the files in the third parent (u
). There are no changes between w
and *
but this brings back u
.
Applying the stash@{1}
, brought back all my changes ...
Again, this is to be expected: git stash apply
tells git stash
to compare the work-tree (for stash@{1}
) and index commits to their parent (*
). Here, there are changes, and it extracts those and applies those to the new HEAD
commit. There is no third parent in this other stash-bag, so apply
is finished at this point.
If you like the result, go ahead and git stash drop
the two stash-bags.