Ran git stash
to stash just one file out of 4 tracked files.
Using git stash show
displays not only that file but the other staged files as well. Why? For example: why does it show anything other than the file "application.xml" that I stashed?
$ git status
On branch some/0.0.1
Your branch is up to date with 'origin/some/0.0.1'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: src/main/java/ServiceServiceImpl.java
modified: src/main/java/util/ServiceUtil.java
modified: src/test/SystemTest.java
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: src/main/java/util/ServiceUtil.java
modified: src/main/resources/application-local.yml
modified: src/main/resources/application.yml
modified: src/main/resources/logback.xml
$ git stash push src/main/resources/application.yml -m "app.xml stashed" <-- stash just one file
Saved working directory and index state On 0.0.1: app.xml stashed
$ git stash list
stash@{0}: On 0.0.1: app.xml stashed
$ git stash show stash@{0} <---------------- Why does it show "staged" files other than the one I stashed (which is src/main/resources/application.yml)
.../java/ServiceServiceImpl.java | 8 ----
.../java/util/ServiceUtil.java | 1
src/main/resources/application.yml | 20 ------
.../test/SystemTest.java | 6 ---
4 files changed, 22 insertions( ), 13 deletions(-)
This is from the man git-stash:
show [-u|--include-untracked|--only-untracked] [] [] Show the changes recorded in the stash entry as a diff between the stashed contents and the commit back when the stash entry was first created.
CodePudding user response:
TL;DR
You see four stashed files because Git really has "stashed" four files. This abuses the word "stash" rather badly, but the four stashed files are the three you had already staged-for-commit plus the one more than git stash push -- <pathspec>
staged for commit into the working-tree commit that git stash push
makes.
Long
The git stash
documentation is, in my opinion, somewhat lacking. It's particularly bad for your case. The documentation is better now than it was 15 years ago, but it's still not great. (Unfortunately, fixing it is hard.)
Fundamentally, git stash
is about making two, or sometimes three, commits. I like to refer to these as the i
, w
, and (optional) u
commits. The i
commit saves the index state, the w
commit saves the working tree state, and the u
commit, if it exists, saves some or all untracked files.
These three commits are tied together so that a single commit hash ID can locate all three of them (or the two, for the two-commit case). Diagrammatically, we can draw these three commits like this:
...--o--o--@ <-- current-branch (HEAD)
|\
i-w <-- refs/stash
/
u
That is, the refs/stash
ref (which is not a branch name) will contain the hash ID of the w
commit, when all is said and done. The w
commit has the form of a merge commit because it has two or three parents: the first parent of w
is @
, the current commit; the second parent of w
is i
, the index commit; and the third parent if it exists is u
, the untracked-files commit.
Now, the index, as is so clearly explained