💾 Git stash

I've been developing websites and web applications for 3 years now. Its inevitable that projects usually, have multiple features to be worked on, and almost always there are multiple developers working on a slice of a feature or multiple features at a time, depending on the requirements and priotities.

In these environments, development is a rapid process! That is why developers sometimes need to switch into other branches for various reasons, among them:

  • review teammate Pull Requests that has higher priorities than their current work.
  • work on a different feature due to priority changes.
  • fix crucial bugs (especially in production).

GitHub Inc.

@frontend_dev Requested Your Review

PR Purpose: change notification layout for new Payments. You can add your review on GitHub.

9:20

Chat
Search
PO

Product Owners

Goran: We need reviews here please. kinda urgent!!

FE

Frontend Team

anyone to review this pls😻

BE

Backend

Aram: reviewing in a sec👀

G

General

FIB is live baby😎

chat
Teams
Calls
Calendar
Activity

At these occasions, its important to keep your current work, so you can come back to it and finish it up. Wouldn't be cool if we could clean the desk to work on something time-sensitive and then be back to what we where doing before?

Jump around Pull Request branches, back to your work, go to main branch to get latest changes, back to your branch, and your work is preserved for you, even those files that are new and haven't been tracked before?

Git Stash to the rescue!

Stash is a spot managed by Git, you can use it to save the current state of your working directory and/or the index, later on, on any branch you want, you can bring these changes back and continue your work!

Save your work

If you have some changes in your current working directory, run this in command line to stash the current state of your working directory:

git stash push

This command will create a stash with all the changes in current working directory and the index, but not the untracked files!

Checkout The difference between HEAD, working tree and index in Git for more information about these terminologies.

If you want to stash the untracked files as well, you need to pass the --include-untracked flag:

# long version
git stash push --include-untracked

# short version
git stash push -u

Its possible you have changed a file and staged it, and then you'll edit the same file again, you'll end up having multiple changes on the same file, some in staged and some in working directory, if you want to stash only those that are staged you can pass --staged flag:

# long version
git stash push --staged

# short version
git stash push -S

I have had cases where I needed to stash some half-baked implementation but keep couple changes so I can use it to implement it in a different way in the same branch, I had acheived this by adding desired files/changes to the staged area and use --keep-index flag to keep said files/changes intact:

# long version
git stash push --keep-index

# short version
git stash push -k

It is worth mentioning that, like commits, stashes also can have a message, makes it easier to identify the stash you want to operate upon.

In case of not providing a message for the stash, like commands above, Git will assign WIP on BRANCH_NAME by default!

To assign a message for the stash use --message flag:

# long version
git stash push --message "Add notifications UI | WIP"

# short version
git stash push -m "Add notifications UI | WIP"

Bring back saved work

After you've stashed your work with git stash push, you can bring them back to your working directory and use it as you need.

Note: Stashes are Git objects, so you can bring them back on any branch that you want, not only the branch that you created the stash on!

There are 2 ways to retrive your stashed changes that is created before:

Pop

Applies the changes in the target stash to your working directory and removes the target stash from the stash list.

git stash pop

When you're creating a stash, Git knows whether the changes are from index(stage) or not, so if you need to retrive the stash and put stashed files that was in staged area before, use --index flag.

As Git Docs stated, this flag will:

Tries to reinstate not only the working tree’s changes, but also the index’s ones.

# long version
git stash pop --index

# short version
git stash pop -i

Apply

Its like the pop command, except it doesn't remove the stash from the list.

NOTE: the --index (or -i for short) is also applicable with this command.

Show stashes

If you're not sure what stashes you have in your list, show the list of stashes with:

git stash list

You can pass Git Log options to filter or change the output of the list, i.e show only the last stash pushed:

git stash list -n 1

If you want to see specific stash's content, use show command:

git stash show <STASH_NUMBER>

# by default it shows the latest stash
git stash show

# specify the target stash
# for example the stash before the last
git stash show 1

By default, show command only shows changes from tracked files, if you want to see untracked files in the output as well, pass --include-untracked flag:

# long version
git stash show 0 --include-untracked

# short version
git stash show 0 -u

In case you want to see only untracked files in a stash, pass --only-untracked flag:

git stash show --only-untracked

And lastly, this command accepts the diff Options if you wanted more complex diffing output, since the command shows minimal information.

Remove unwanted stashes

Believe it or not, this magic sometimes gets overwhelming when you have more than a handful stashes. Keeping a stash for long time is rare, personally I commit the changes and send it to a remote repository if I think it might be needed in a week or two, since local changes are subject of unrecoverable losses, due to general computer failure or mistakenly destroying the stash.

OK back to removing stashes, unwanted stashes, right, you get the idea!

Git uses drop terminology for popping a stash from the list without applying it on the working directory, so to drop a stash run:

git stash drop <STASH_NUMBER>

# drop latest stash
git stash drop

# drop 2nd stash before most recent one
git stash drop 2

In cases where you have multiple stashes and want to remove all of them, using drop command takes some time, instead, you can use clear command to drop all the stashes together:

git stash clear

NOTE: Droping/Clearing stashes can be unrecoverable, take your time before executing these commands or you might lose hours of work!

Suppress the logs

The feedback can be useful to know the effect of your command execution, but when you got used to these commands, that feedback can be annoying, fortunately Git accepts --quiet or -q flag to suppress the feedback:

You can pass the flag to: push, pop, apply, drop commands.

VSCode's built-in Git support

Terminal is amazing, it gives you lots of control over command execution, but it can be cumbersome for dead-simple use-cases. A Git Client might help with these straighforward commands, and what is better than your code editor?

VSCode is my favourite code editor, I've been using it for a long time, two features of VSCode changed the way I approach solving these problems:

  1. VSCode's command palette: lets you quickly find a command and execute it, whether its a built-in command or a command provided by extensions, couple keyboard key hits and you're done!
  2. VSCode's built-in Git support makes it very easy to execute common Git commands, plus the first point, it's true game changer!

Since using mentioned points, my productivity has boosted immensely. After doing it for multiple times, you build a muscle memory for it, hence you wont disrupt your train of thoughts since it takes not more than a couple seconds to execute and forget about it!

Having said that, there are complex cases you might need to operate in the terminal where you have more control over the command, just use the tool that best suits the task.

At the end, I want to show you how you can push, apply, pop and drop stashes within seconds in VSCode:

Git StashDev Tools