Hi guys. In today’s post, will talk about git. At this point, you probably already know that all the usual commands (e.g git-add, git-checkout, git-commit) are enough for you. With that small set of commands, you can solve most of your problems. It’s the real Pareto Principle where you, with 20% of the commands, can solve 80% of the problems, and that’s amazing.
We’re going to discuss a scenario that likely fits the other 20% of the problems when you get interrupted in your normal workflow. What to do in this case? Maybe you can even have a good idea of how to solve it using that small set of commands, but maybe you could do it more efficiently (and elegantly) using git-stash.
Let’s see how.
The normal workflow
Think of your workflow. Whatever it is, you probably just checkout a branch, do some good code, commit your changes (with a good commit message of course), then push your changes to the remote repository.
The workflow you’re using doesn’t matter for this article. You’ll most likely do a similar process as described above at least once in your workflow.
As the good software developer that you are, you commit your changes in a semantic and well-packaged way, meaning you only commit the code when you have a block of effort. But what if you get interrupted before finishing a committable change?
Things can go wrong and maybe you have to stop what you’re doing right now and work on an urgent fix. What do you do?
Naively Solving the problem
You could easily commit your changes even knowing that they’re not committable. They are incomplete. You would be solving the problem, and would just need to think a bit about a good message to go with that. I have not seen people doing it in a good way, though. They usually write only "WIP" in the commit message (please don’t do that).
That works, especially if you are a creative person. You have to be one to avoid a mess in the commit history.
What if we could stop the current work exactly as is and go fix that other issue (and save the day)? That would be great, and it is, that’s where git-stash comes in.
You’re probably asking: but what git-stash is and how does it work? Reasonable questions, I would say. Let’s see what the documentation says.
Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory.
The command saves your local modifications away and reverts the working directory to match the HEAD commit.
That’s exactly what we want. It’ll stash our changes and get back to the last commit in the current branch (HEAD commit). In the next sections, we’re going to simulate the scenario we described before.
Git-stash to the rescue
To save your current changes for later, you just need to run the following command:
git stash
By default, it only stashes tracked files but you’ll likely need to do it for untracked ones too. When we’re adding features, we create files, so you can run:
git stash --include-untracked # or git stash -u for short
You can stash stuff as much as you need, as it will work as an actual Stack. Pretty simple. A new stash goes to the top of the Stack, and when you apply the stash it’ll be removed from the top.
Applying the stash means getting changes back. Let’s see it working in the example.
Our repository
In the image below we can see a repository with my NeoVIM settings (see the link in the References section).
Running git log
in the main
branch we can see (disregard the typo, please (: ).
Starting a new feature (and getting interrupted)
So we’re going to work on some exciting features!! Le’s create a new branch and add some stuff.
git checkout -b new-feature && echo 'my amazing feature' >> new-file
We’ve just started our new feature. Everything was going fine until then, but before we were prepared to commit something goes wrong in the main branch (rats!!).
Instead of committing an incomplete effort, we can just stash our changes by running the command below.
git stash -u -m "I'm going to fix some urgent stuff"
NOTE: The -m option allows you to define a message for that stash so you can identify it better when some operation is needed in the future.
By running the commands above you’ll see something like the one shown in the image below.
Now that we stashed our changes on the new-feature branch, we can go ahead and work on the main branch.
Before going to fix the urgent bug let’s see the stashes (only one in this case). We can do this by running the following command.
git stash list
The output should contain something like shown below.
stash@{0}: On new-feature: I'm going to fix some urgent stuff
In the output, we can see the stash index (zero in this case), the branch name where was this stash created (new-feature in this case), and the message we gave to this stash.
You can also see what the stash contains by running the command git stash show -u
. This command also accepts a --index
option that allows you to specify the stash
.
Fixing the bug
We paused our changes on new-feature branch, now we can work on our main and fix what’s needed.
As you may know, we are not fixing real things here, so let’s simulate by running:
git checkout main
echo 'this fixes everything' >> fix-file
git add .
git commit -m "fix that terrible bug"
We’re committing directly to the main, and this might be unusual for non-personal projects, but the workflow doesn’t matter, remember? Just keep in mind you could have created a new branch called fix-something from main and followed your team workflow, no problem at all.
Back to the feature (applying stashed changes)
The bug is fixed, so we can go back to work on the new-feature branch. Naturally, we want to start right where we stopped. To do that, we must apply the stash we created before.
This can be done in a couple of ways, the most common is by running the following command:
git stash pop # make sure you're in the same branch you created the stash
By running this command you’ll apply
and drop
the stash from the stack. In this case, we have only one so it doesn’t make much difference.
If you have more than one and want to apply some specific stash you can pass the --index
option to this command (e.b git stash pop --index 2
).
When you apply it, whatever changes you stashed go back into the current branch. So, make sure you’re in the same branch where you created the stash to avoid unexpected behaviors.
In our case, we must run the following commands.
git checkout new-feature
git stash pop
The output of this command should look as shown below.
Already up to date.
On branch new-feature
Untracked files:
(use "git add <file>..." to include in what will be committed)
new-feature
nothing added to commit but untracked files are present (use "git add" to track)
Dropped refs/stash@{0} (f4942ebaed4ef0407cf9613a8efceabeb8982e98)
As we expected, our untracked new-file came back and the stash was dropped.
Avoiding conflicts with git-stash
Conflicts can happen when using git-stash. They can arise when you stash the changes and update the same files in the branch, or even if you apply the stash to the wrong branch. To avoid that you can:
- Make sure you are in the correct branch before running
git stash pop
- Work safely by applying the stash with
git stash apply
. It works like pop but doesn’t drop the stash. So, you can revert any bad code without losing the changes you stashed. Once you ensured everything is all right, you can drop the stashes manually by runninggit stash drop
.
What if a conflict happens? Don’t worry, when this happens you can solve it by staging (or not) the files. The stash that caused the conflict is not dropped. It means you can apply the stash correctly (or just drop it if you want to).
Summary
In this post, we learned a useful git
command. At first glance, it might seem overkill and we may tend to resist using it. But, in my humble opinion, you shouldn’t. This kind of command saves your time and commits history, thus making your work better, which makes you a better professional.
We’re finishing this post but that was the first part only. I plan to bring another post where we can solve this same problem in an even better way.
Let me know if you have any questions, and if this content was useful for you, consider sharing it with everybody else who might have an interest.
That’s all, see ya!
References
- Git stash documentation: https://git-scm.com/docs/git-stash
- My dotfiles repository: https://github.com/geeksilva97/dotfiles
- Image credits: https://wall.alphacoders.com/big.php?i=985805
We want to work with you. Check out our "What We Do" section!