How do we stash changes in Git?

GitLinuxOpen SourceSoftware & Coding

This question can be rephrased as "How to save work in progress (WIP) in Git and return to it later when convenient?"

The problem − When we switch branches, Git resets our working directory to contain the snapshot stored in the last commit of the target branch. For example, if we switch from feature to the master branch, Git will replace contents in the working directory with the last commit of the master branch. But if we have local changes in our working directory that we haven't committed yet, these changes will be lost. In this situation, Git will not allow us to switch branches. Let us see how this happens and how we should solve this.

Example − Create an empty repository and execute the commands given below. The example shows that we are working in a feature branch, editing and adding files. Suddenly, we might have to switch to the master for an immediate bugfix in the master branch. It will not allow us to switch to the master branch as we have some work in progress (WIP) in featurebranch.

$ git init                  // initialize an empty repo
$ echo abc>abc.txt          // create a file and add some text to it
$ git add abc.txt           // stage the file
$ git commit −m abc.txt     // commit changes to the repo
$ git checkout feature      // Switch to the feature branch
$ git log −−oneline         // Display commit history
$ echo lmno>lmno.txt        // create a file and add some text
$ git add lmno.txt          // stage the file
$ git commit −m 'save lmno' // commit changes to the repo
$ echo lmno lmno>>lmno.txt  // append data to the file
$ git checkout master       // Switch to the master branch

Git prompts us to stash the changes when we try to switch the branch.

delI@DESKTOP-N961NR5 MINGW64 —/Desktop/Internship/Batch_01/Session03/git/test-re
po (feature)
$ git checkout master
error: Your local changes to the following files would be overwritten by checkout
Imno. txt
please commit your changes or stash them before you switch branches.

Pushing Work In progress (WIP) to stash

We don't want to commit our changes as we are not done yet. In situations like this we need to stash our changes. Stashing means storing things in a safe place. We are going to store this in a separate stash area in the Git repository. Stashing will not be a part of our history. Let us see how it works.

The following command pushes the work that is lying in the staging area and is pending to be committed into a stash. The −m flag is used to provide a stash message.

$ git stash push −m 'working on lmno file not completed '

By default, untracked files are not included in your stash. To push untracked files, i.e., files in the working directory, we need to include the option −am flag. Let us see an example −

$ echo hello > newfile.txt //create a file in the working area
$ git stash push −am 'my new stash' //push untracked files into the stash

To view all the stashes, use the command − git stash list

$ git stash list

The command returns all stashes. Note that the latest stash will be listed at the top of the list, i.e., at index 0.

stash@{0}: On feature: my new stash
stash@{1}: On feature: working on lmno file not completed

After stashing, the working tree will be clean. Now the collaborator can switch to any other branch and do some important work. Once done, the collaborator can switch back to the feature branch again. At this point, we decide to apply one of the stashes to our working directory.

Applying Stash

To apply stashed changes back to our working directory we can use the following command −

$ git stash apply <index_number>

The following example applies stash sequences at index 0 and index 1

$ git stash apply 0
$ git stash apply 1

The output shows that the stashes have been applied and now our working directory will contain all changes as expected.

dell@DESKTOP−N96LNR5 MINGw64 /e/tut_repo (feature)
$ git stash apply 0
Al ready up to date!
On branch feature
untracked files:
(use ''git add <file>… " to include in what will be committed)

newfile. txt
nothing added to commit but untracked fi les present

dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (feature)
$ git stash apply 1
On branch feature
Changes not staged for commit:
(use "git add <file>…" to update what will be committed)
(use "git restore <file>… " to discard changes in working directory)
modified: Imno.txt
untracked files:
(use "git add <file>… " to include in what will be committed)
no changes added to commit (use "git add" and/or "git commit −a")

We can verify contents of our working directory using the following commands −

$ ls // lists contents of the current directory
$ cat newfile.txt // lists contents of newfile.txt
$ cat lmno.txt // list contents of lmno.txt

The output is as shown below −

//output of ls
abc.txt lmno.txt newfile.txt
//output of cat newfile.txt
//output of cat lmno.txt
lmno lmno

Cleaning the Stash

Once stashes are applied successfully, we may need to clean up things as stashes are not removed by default. We can use the following command to drop a specific stash.

$ git stash drop 0

To clear entire contents in the stash in one go, we can use the following command

$ git stash clear
Published on 20-Feb-2021 08:58:22