When stashing some changes, Git creates two separate commits, 'WIP on branch' and 'index on branch':
$ git log --graph --all * commit 98aac13303ca086580c1ec9ccba5fe26c2a8ef3c |\ Merge: 7d99786 82c5c76 | | Author: Tieme <[email protected]> | | Date: Wed Nov 19 09:58:35 2014 +0100 | | | | WIP on development: 7d99786 Last real commit | | | * commit 82c5c763357c401135675a39bfabf9b7f6805815 |/ Author: Tieme <[email protected]> | Date: Wed Nov 19 09:58:35 2014 +0100 | | index on development: 7d99786 Last real commit | | | * commit 7d9978637a0e1ef92f2432189bdebf2317f0b2f0 | Author: Tieme <[email protected]> | Date: Tue Nov 18 17:32:33 2014 +0100 | | Last real commit |
I looked up the documentation for this but it does not make it clearer:
A stash is represented as a commit whose tree records the state of the working directory, and its first parent is the commit at HEAD when the stash was created. The tree of the second parent records the state of the index when the stash is made, and it is made a child of the HEAD commit. The ancestry graph looks like this:
.----W / / -----H----I
where H is the HEAD commit, I is a commit that records the state of the index, and W is a commit that records the state of the working tree.
Why are there 2 commits created and not just a single one for the files I changed ?
Git stash vs.A commit is part of the public git history; a stash is stored locally. A commit creates a new save point on a branch; a stash reverts to a previous save point. A new commit leaves files in the working tree unchanged; a stash resets files in the working tree to the previous commit point.
If you made two stashes, then just call git stash pop twice. As opposed to git stash apply , pop applies and removes the latest stash. You can also reference a specific stash, e.g.
If you're using git stash you don't need to worry about separate commits at the moment. Run the stash command, then do whatever else it is you need to do, then pop your changes back from the stash and then make your commits how you want them.
As Sajib Khan answered, git stash save does make commits. More precisely, if git stash save does anything (sometimes it does nothing, if there are no changes), it makes at least two commits. If you use the --untracked or --all flag, it makes three commits.
git stash
differentiates between the changes you have on your index and the one you have in the working tree and creates commits for both of them.
Some background
Using git it's possible that the changes you have in your working tree (the files your directly work with) are different from the changes you have on the index.
Adding only a limited number of files to the index, or with git add --patch
even adding single changed lines in a file will leave your index in a different state as the working tree.
This is a good thing, because it enables you to create commits which focus on one specific task/feature.
It's even possible that you have changes on your index which aren't anymore part of your working tree. You can test it by adding some changes to the index (git add
), manually removing them from the file and then creating a commit (git commit
).
The commit will still contain the changes you added in the first place, although they don't exist in your working tree anymore.
If you have trouble understanding the difference between the working tree and the index you can take a look at this question.
What exactly is happening?
Now the statement from the beginning should make more sense. One "stash commit" contains all changes you had in your working tree (the files you directly work with) and the other contains the changes you had added to your index.
By default git stash pop
or git stash apply
only tries to reinstate the changes you had in your working tree and ignores the changes you had on the index. It's possible to tell git stash
to try reinstating your index too by using the --index
flag (git stash (pop|apply) --index
).
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