Reputation: 31212
I went into a branch and did some work. I wanted to go into another branch but didn't want to commit so I did git stash
. Then I did git checkout <otherbranch>
. I did some work there and, just like in the first branch, I wanted to switch out of it before committing the work. So I did git stash
there too. I switched back to the first branch and tried to unstash it (git stash pop
) thinking it would get the stash from that specific branch. I was surprised that it unstashed the stash from <otherbranch>
(latest stashed). I was under the impression that stash is branch-specific but this behavior indicates that there is only one stash for the whole local repository.
Is git stash
branch-specific or for the whole repository? If it is for the whole repository, can I pass options to it to make it branch-specific?
Upvotes: 159
Views: 56998
Reputation: 28979
stash workflow:
Whenever you have to switch the branch and your not ready to commit, save your changes to the stack
git stash push -m "Your custom stash message"
(if you dont want a custom message, simply use git stash
).
When you return to a branch, you can see the stash list like this:
git stash list
If you're on branch FixIssue0203
you could use use git stash pop
because this will apply the top stash@{0}
and remove it from stash.
However, if your in branch ImproveReadme
you should first apply the stash 1 git stash apply stash@{1}
and then remove stash 1 from stack git stash drop stash@{1}
.
That's it!
If you want to only stash individual files, things are a bit tricky. Read https://stackoverflow.com/a/12305243/2311074 for more. If you happen to use jetbrains, they have a feature called shelve so that you can cherry pick files that you may want to reuse later: https://www.jetbrains.com/help/idea/shelving-and-unshelving-changes.html (It's not part of GIT)
Upvotes: 51
Reputation: 534925
Is git stash branch-specific or for the whole repository
Both.
Stash is for the "whole repository" in the sense that it is a single stack. Entries in the stash list do not come and go when you switch branches. The most recently pushed entry is the one that will be applied if you say git stash pop
or git stash apply
without further specification of which entry you want — even if you switched branches in the interim.
But each stash entry is loosely bound to the branch you were on when you created it. When I say "loosely bound", I mean that trying to apply a stash entry to a different branch than the one from which it was created is quite likely to get you into difficulties.
For this and many other reasons, it is useful to give a stash entry a message at the time you create it (using the -m
option). That way, you can look through the list (with git stash list
) to find the one you want and to know what you stashed it for and what you were doing when you stashed it.
Even better: don't use git stash
at all. It's a pretty skanky mechanism, full of gotchas. To save your work, make a normal commit.
Upvotes: 1
Reputation: 2770
This might not answer your question but I believe it answers the use case you are referring to eg what Trevor Boyd Smith alluded to in the accepted answer.
"Here is a common real-life scenario that demonstrates the value and the usage the commit and reset commands:
you are working on feature branch X and your code doesn't even compile or pass the tests there is a bug that is higher priority than the current new feature and so you must start work immediately on the bug fix rather than do a git stash (and the stash gets lost in the mix because you have many stashes and many branches)" Bolded this because this happens to LOTS of people.
What I do is have literally 5 copies of the same repository and name the root folder appropriately so you can switch to a working branch in literally seconds without losing track of where you are. You can even open a second instance of your IDE so if you a multi tasker you can work on your 20 minute hotfix in folder2 and go back to your larger task in folder 1 when you are done.
It requires some house keeping of which folder is used for what, they should all be regularly kept up to date. I also recommend that root of these working directories be backed up/sync'd regularly to some kind of versioned file storage so you can always get yourself out of any mess you get into. Git purists may disagree with this workflow, however it works for myself and I've seen many other developers use this workflow.
Pros and cons. Personally I find this the fastest way to do the use case mentioned by trevor without worrying about a stash getting lost or which branch the stash should be re-applied to. Means you can merge/diff files from your uncommitted/unstashed/completely broken mess in your current branch that you don't ever want committed by accident as well.
Upvotes: 1
Reputation: 2292
No and No. git stash is per-repository.
Here is a nice page on how to use it.
Upvotes: 88
Reputation: 19233
git stash
is not per-branch.
git stash
(which can be lost easily when you have lots of stashes and branches) git commit
to save the unfinished code in your branch and when you are ready to finish the code do a git reset ${COMMIT_HASH_VALUE}
to get the unfinished code backgit commit
and git reset
when used together correctly can simulate a git stash
for a specific branchHere is a common real-life scenario that demonstrates the value and the usage the commit
and reset
commands:
git commit
on feature branch X
COMMIT_HASH_VALUE
for latergit reset ${COMMIT_HASH_VALUE}
(FYI the default for git reset
is --mixed
)
Upvotes: 28
Reputation: 487815
To see the current stash stack:
git stash list
To pick a specific stash from the stack, refer to it by the stash@{number}
shown by the above.
If you want the behavior to be per-branch, you can just make a commit (or multiple commits) on the branch. You can always "unmake" the commit(s) later (e.g., with git reset
, either --soft
or --mixed
; see the git reset documentation; or with git rebase -i
to keep only the eventual "real" commit(s) while discarding the temporaries).
(To really emulate git stash
you need at least two commits, one for the index state and one for the work-tree state. If you're not planning to save and restore the index state, though, you can just git add -A
the entire work-tree state and put that in the temporary commit. Alternatively, git stash
is a shell script so you could copy and modify it pretty easily to make it work per-branch by default, using, e.g., refs/pb-stash/branch
as its working name-space, rather than the single global refs/stash
for the entire repo. You'd still be able to bring a stash from one branch to another by naming it explicitly.)
Upvotes: 63