nonopolarity
nonopolarity

Reputation: 150976

If Git Stash saves Diffs, then why can't it be applied to a different branch?

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

Answers (2)

Matthieu Moy
Matthieu Moy

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

tobiasvl
tobiasvl

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

Related Questions