I never liked the way ‘stash’ works in Git. It is not really obvious to use, and moreover, it is a nightmare when a conflict arise during a rebase.
This article discuss about the stash concept in Git, its advantages and disadvantages and why I recommend not to use it at all.
The Stash concept
Of all concept intruduced by Git, stash is a weird concept, people knows about it but also know that it cannot do everything.
Stash is basically a list of patch, placed aside in stack, to allow you to save a commit for later but without creating a commit.
But here is the main flaw of stash: it does not create a commit while in Git it is so easy to manipulate, rearange, squash/fixup commits.
I never use stash, I don’t like it because of the following points:
- no graphical view: I like seeing what things are looking like, and I love GUIs. I mostly use git gui , gitk , and on Mac OSX , Git Tower. None of these tools is able to display the stash properly.
- why do you “stash” your work? It is a list of change for “later work”. But this “for later” is actually closely linked to a particular state of the commit tree. A given entry in the stash has high chance to fail applying correctly in case of conflict
- conflicts… once you have a conflict, you are almost pretty sure to have lost you stash. That is a lame because…
- you have lost it if you pop it! I mean, I do mistakes every day, I need tools that allow me to do error and revert easily to a know, previous state. Of course, you can use git apply but you still have to modify your code prior to applying the patch to avoid conflicts.
That is why I never use stash.
So, how to save stuff “for later”?
Create a branch. Create a tag. Create a commit on top of a fresh new branch named “WIP” (for “Work In Progress”). If a conflict arises after a rebase, I simply use the same merge tool than in normal rebase/conflict situation. And moreover, you will not risk to loose your stash.
But what if you rebase and missing something during the merge?
Remember, commit are always present in the git tree, even if you don’t see them in git log or gitk.
Dandling commits are kept 15 days by default and only removed by git gc after this delay.
Use this magic command to find out the “WIP” commits in case you failed the current rebase:
gitk-entier-history='gitk --all $(git log -g --pretty=format:%h)'
Don’t use this command on a project such as the Linux Kernel with millions of commits, but on every projects I have worked on so far (big data projects, web projects, millions line of code project with several years of history), this command saved hours.