Knowing how to git save local changes temporarily lets you switch branches without losing your changes. git stash is one of the most crucial commands to use in the process.
However, due to the complexity of the stash command, it could be challenging to understand when, and how to apply or distinguish it from other commands such as git stage, commit, checkout, diff, and reset. Read on to find a solution.
git stash cheat sheet to save local changes without commit
Here is a list of commands to apply as you git save local changes temporarily.
1. git save local changes temporarily with a reminder.
git stash save "<optional message>"
2. View temporarily saved changes
git stash list
3. Inspect changes in a specific stash
git stash show <stash name>
4. Restore the stashed changes while keeping the copy
git stash apply <stash name>
5. Restore discarded changes and delete the backup
git stash pop <stash name>
6. Delete a stash without restoring changes
git stash drop <stash name>
7. Delete all stashes without restoring changes
git stash clear
In a complex form, use the stash command as follows.
8. Git save untracked local changes temporarily
git stash -u
9. Forward stashed changes to a new branch
git stash branch <new_branch> <stash name>
10. Interactively save the changes
git stash -p
Examples of situations to save local changes temporarily in git
Knowing typical scenarios to use the stash commit is a milestone in identifying when to git save local changes temporarily. Here are some of the situations. Assume,
- You work in the main branch. A collaborator asks you to fix an issue in their branch, but you don't want to forward your unsaved commits to their branch.
- You work on file A. You have staged some changes. Just as you are about to commit the changes, you realize a missing step between the previous commits and the one you are about to make. You want to inject the features and return to the current work in progress without losing the changes.
- You work in the main branch. You have made the first two commit commits. As you make the third one, you realize that the changes were meant for a feature branch, B.
- You have added a feature, but not sure whether you need the changes now. You realize it would be best to git save local changes temporarily, proceed with commits in another branch, and return when you have a definite role for the changes.
Let us see how to solve some of the above challenges practically.
Lab setup to explore git save local changes temporarily
Since situations that affect saving local changes temporarily often arise from a shared repo, let us clone a repo and handle the changes properly. I am creating one on GitHub called temporary_save
.
I grab its URL, clone it locally, cd
into the temporary_save
folder, and modify the repo as follows.
Create a branch.
git branch b
create index.html
file.
touch index.html
Stage it.
git add index.html
Lastly, let us commit the changes.
git commit -m "Add empty HTML file"
Now that we have something to practice git save local changes temporarily, let us see how git stash works.
How to properly git save local changes temporarily
Use the git stash save command
git stash save "<optional message>"
to discard changes on a modified tracked file.
OR
Supply the -u
option to save untracked changes
git stash -u
OR
If you have many changes and want to choose what to or not stash, supply the -p
option.
git stash -p
OR
If you want to start a new branch with the stashed changes, run the stash branch command
git stash branch <new_branch> <stash name>
Modifying a file means making changes to an already committed file. A tracked file has some changes staged or committed. The opposite of a modified file is a new file, whereas the antonym of a tracked file is an untracked file. Either way, such a file has neither been staged nor had its changes committed.
Assume we start modifying the HTML
file. We append HTML
boilerplate as follows.
cat >> index.html <!DOCTYPE html> <html lang="en"> <head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title> </head> <body> ​ </body> </html>
As we are about to stage the changes, a workmate, modifying branch b
, needs an urgent fix to an issue on their branch.
Since we neither want to switch branches with the changes nor combine them with theirs, we git save local changes temporarily using the git stash command.
First, check the repository status before discarding the changes.
cat index.html git status git log
We have changes awaiting indexing, an HTML
boilerplate, and the history has two commits: from the clone and the initial commit of the HTML file.
Stash the changes.
git stash save "Pending HTML files in the main"
Recheck the repo status and index.html
.
git status cat index.html
Our changes got discarded, and the repo is back to the last commit stage. Neither can we see the boilerplate.
View the temporarily saved changes
We can view the changes after doing git save local changes temporarily. The stash list command
git stash list
shows the structure of the temporarily saved changes.
For a deeper view of the temporarily saved changes, use the stash show command with the stash name
git stash show stash@{0}
or the patch option.
git stash show -p
But how do the above structures temporarily save a file? Find out below.
How exactly does the stash command work?
Git stash is technically a commit, and you can log its history as you would after the git commit.
git log --oneline --graph stash@{0}
Where stash@{0}
is the commit. The zero 0 in {0}
shows the temporarily saved file's index from the HEAD: a special file in .git/refs/stash
. On main tells us the branch whose changes we temporarily saved, whereas Pending HTML files in the main is the reminder.
On stashing a change, git snapshots it as an object, referencing the latest stash in the .git/refs/stash
file. That is why logging the history reveals the stashed changes' HEAD, which is refs/stash
.
Distinguish git stash from other git commands
Git stash vs the commit, stage, and reset commands
Both stashing and committing changes create a new record in history. Mostly, git stash and git commit are descendants of the git stage.
Staging a file notifies git to snapshot the changes in the index. From there, you can stash the changes, creating a queue of saved changes running parallel to the current development line. Alternatively, you can commit the changes, stacking the changes onto the current development line.
Both git stash and git reset reference subsequent changes from a point: the HEAD commit in reset and .git/refs/stash
in a git stash. Both commands remove changes from the current branch.
However, as you will see in the following sections of this article, you can restore changes discarded by git stash. On the other hand, it is almost impossible to recover the changes after doing a hard reset on them.
The stash command vs git diff
Git stash show reveals the number of new lines added on doing git save local changes temporarily. It is comparable to git diff since git diff also shows new insertions on a file.
However, the difference between the git stash show and the diff command is that git diff echoes new insertions before stashing the changes. In contrast, the stash show command tells the differences after the temporary save.
How to restore git's temporarily saved changes
Use git stash apply to restore the changes while keeping the copy.
git stash apply stash@{0} git stash list
Alternatively, use the stash pop command to restore the changes and clear the copy
Let us first stash the restored changes.
git stash save "Restash pending HTML changes"
Then list and pop the changes.
git stash list git stash pop stash@{0} git stash list
How to delete a copy of the temporarily saved changes
Delete one record of the temporarily saved changes using git stash drop.
git stash drop stash@{0}
OR
delete all copies with the clear option.
git stash clear
Final word
That is all it takes to git save local changes temporarily. If any conflict error arises after restoring the changes, use git merge or rebase to restructure your repo. You can then stage, commit and push the changes.
git add . git commit -m "Wrap it up" git push