Reputation: 150976
As I understand it, Git Stash is a collection of diffs.
So for example, if I have a whole repo with a single file foo.txt
The 32 lines of the file is just
Lorem Ipsum 01
Lorem Ipsum 02
Lorem Ipsum 03
...
Lorem Ipsum 30
a first line: good
a second line: bad
And I committed everything.
Now I create a new branch:
git checkout -b feature123
And now that I am on this branch, I change the word good
to better
, and bad
to worse
.
Now, just suppose my program manager comes over and say, "Urgent! We have to change the 01 to 011 and 02 to 022".
So I stash the changes, and then change to the master
branch:
git stash
git checkout master
and I changed the 01
to 011
, and 02
to 022
as he requested.
And say, I want to incorporate the changes that I "stashed" earlier to the master
branch:
git stash apply
but it will error out:
error: Your local changes to the following files would be overwritten by merge:
foo.txt
Please, commit your changes or stash them before you can merge.
Aborting
Why is that? Can't it just apply the collection of diffs to foo.txt
?
(P.S. I can commit first, and then use git stash apply
, and be able to apply those diffs to foo.txt
. But why not before the commit? So git stash
really just saves a collection of diffs -- to repeat precisely: a collection of diffs, and then do a git checkout .
(to abandon all changes). Is that true?)
Upvotes: 2
Views: 193
Reputation: 16507
Git Stash is a collection of diffs.
Not really. a stash is a collection of commit objects, each of them records a complete snapshot of the project. git stash pop
does a merge between the current head, the stash, and the commit the stash is based on.
It would be possible in theory to perform a merge on locally-modified files, but in practice:
This would be a really bad idea for merge
because it would encourage users to do "evil merges", i.e. have both merge-related an manual changes in the same commit. As a consequence, it is forbidden for a merge to touch locally modified files, and stash
uses the same mechanism as merge
, hence forbids it the same way.
The index makes things more complex than they appear to be. If a file had unstaged content, and you wanted to apply a stash to it, then there would be no proper way to define what should be the content of the index at the end of the stash application. Actually, stash pop
is allowed to touch files for which the index matches the working tree.
Note: your problem is not the fact that you are on different branches, but that you have uncommited/unstaged changes. You did these changes while on branch feature123
, but they are preserved when switching branches with git checkout master
.
Upvotes: 4
Reputation: 580
man git stash
says the following, under pop
(which also applies to apply
):
The working directory must match the index.
So you are correct, it can apply the collection of diffs to foo.txt
, but not if you have unstaged local changes. If you're confused about the difference between the working directory and the index, perhaps this answer can help.
Run git add hei.txt
, and you will be able to apply the stash.
Upvotes: 1