Alex headshot

AlBlue’s Blog

Macs, Modularity and More

Git Tip of the Week: Stashes

Gtotw 2011 Tip Git

This week's Git Tip of the Week is about keeping work in progress safe, known as stashing. You can subscribe to the feed if you want to receive new instalments automatically.


Drop everything bugs

Sometimes, when you are working on a problem you need to drop it suddenly in order to work on a different problem, like a critical bug that has been reported against a production version of your code.

Whilst you could easily create a new checkout of your project with the specific branch, it's faster to switch branches in Git natively, and saves setting up other tools like an IDE or a test server.

The problem is, your work may not be in a fit state to commit at the time the bug comes in. Rather than committing a half working state, you ideally want to save the work in progress (including dirty, uncommitted files), to permit you to switch to the higher priority issue, and resume when necessary.

Git Stash

This is where git stash comes in handy. This takes a working tree and files it away in a location which can be retrieved at a later stage. The stash can then be popped to get the changes back as they were prior to the stash taking place.

To create a stash, just run the git stash command. You can see what stashes are present with git list:

$ git stash list
$ touch example
$ git add example
$ git stash
Saved working directory and index state WIP on master: dc3ea83
HEAD is now at dc3ea83
$ git stash list
stash@{0}: WIP on master: dc3ea83
$ ls example
$ # do emergency bugfix here, and afterwards
$ git stash pop # or git stash apply
$ ls example
example

Here, we created a new stash which contained the example file. Once we'd done the stash, we were reset to the current commit (i.e. a clean workspace), so the example file is no longer present.

We can list the available stashes with git stash list, which gives them their identifier (in this case, stash@{0}) which can be used to identify the changes. (It defaults to the last stash if not specified.)

The stash identifier also includes what branch the stash was created from. Importantly, once the stash has been created, applying (or popping) the stash results in just the differences being added, rather than resetting back to a specific previous state. This allows subsequent changes to be made on the branch, followed by replaying the stash changes on the current version of the branch afterwards.

Git stash can be used to avoid merge conflicts with work-in-progress code. Simply stash before doing a pull, and unstash afterwards, as the example in the manpage shows:

$ git pull
...
file foobar not up to date, cannot merge.
$ git stash
$ git pull
$ git stash pop

Notes

  • The stash only applies to added files; it doesn't apply to untracked files. If you want to add untracked files as well, you need to run git add --all prior to running git stash operation.

  • The WIP stands for Work In Progress, since it's not obvious to non-English native speakers.

  • git stash pop will remove the stash from the list; git stash apply will keep the stash in the list

  • The {0} represents the last stash you did, the {1} represents the second to last, and so on. This syntax also turns up elsewhere (e.g. reflogs).

  • Individual stashes can be removed with git stash drop, or git stash clear to get rid of all of them.

  • Git stashes are stored as commit objects, but the branch HEAD isn't updated to point to them. Instead, they are referenced from a reflog entry in .git/logs/refs. You can use git show stash@{0} to see a stash.


Come back next week for another instalment in the Git Tip of the Week series.