ZANARDI Bruno

Software Developper

About
Resume

Git Blog

How To: Git "drafts"

previous home

related commands:
stash

Sometimes, you will have/want to switch branches but you have uncommited changes in your working directory. These changes are in an unstable state, so you can’t commit them.
Don’t worry, git has a solution for you: git stash.

Stashing you work

Let’s show the working directory state:

$ git status
On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: <file_2> modified: <file_3> Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: <file_1>

To be able to switch branches, your working directory must be clean. You don’t want to commit these changes? Make a “draft commit” with stash:

$ git stash save
Saved working directory and index state "WIP on master: <hash> <last_commit_msg>" HEAD is now at <hash> <last_commit_msg> (To restore them type "git stash apply") $
$ git status
On branch master nothing to commit (working directory clean)

Now you can switch branches.

The stash save command creates a “draft commit” and store it out of the history, in a stack.

If the working directory looks like this:

$ git status
On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: <file_1> modified: <file_2> Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: <file_1> modified: <file_3> Untracked files: (use "git add <file>..." to include in what will be committed) modified: <file_4> modified: <file_5>

a simple git stash save will do:

$ git stash save
Saved working directory and index state "WIP on master: <hash> <last_commit_msg>" HEAD is now at <hash> <last_commit_msg> (To restore them type "git stash apply") $
$ git status
On branch master Untracked files: (use "git add <file>..." to include in what will be committed) modified: <file_4> modified: <file_5>

and you still can’t switch branches. You must use the -u (aka --include-untracked) option:

$ git stash save -u
Saved working directory and index state "WIP on master: <hash> <last_commit_msg>" HEAD is now at <hash> <last_commit_msg> (To restore them type "git stash apply") $
$ git status
On branch master nothing to commit (working directory clean)

List stashes

To see all stored stashes, use stash list:

$ git stash list
stash@{0}: WIP on master: <hash_1> <commit msg> stash@{1}: WIP on master: <hash_2> <commit msg>

In this example, there is two different stashes and it is possible to access both.

Re-use stashes

There is two usable commands to get datas from stash and re-put it into your working directory: stash apply and stash pop.
These two commands will apply the stash content to the working directory. Be aware the fact that applying a stash may result in conflicts you will have to handle manually. The main difference between these commands is what happend after: apply will do anything, pop will remove the stash from the stack (if no conflicts appeared).

$ git stash apply
$ git stash pop

By default, apply and pop will apply the last added stash. If you want to apply an other stash, run:

$ git stash apply stash@{x}
$ git stash pop stash@{x}

where x is the number found in list.

What’s in a stash?

To show the changes recorded in the stash as a diff between the stashed state and its original parent, use the command:

$ git stash show
$ git stash show stash@{x}

Remove stash from stack

Once you don’t need a stash anymore (or after handling conflicts resulting from a pop), you can remove it from the stack with

$ git stash drop
$ git stash drop stash@{x}

Create a branch from stash

It is possible to start a branch from a stash, and easily. The command will do: creates a new branch from where you were when you add the stash, apply the stash and drop the it if it applies successfully:

$ git stash branch <name>
M <file_1> M <file_2> Switched to a new branch '<name>' On branch <name> Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: <file_1> Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: <file_2> Dropped refs/stash@{0} (<hash>)

Other options

You can prevent staged changes to be added to stash with git stash save --keep-index.
As for git add, you can use git stash save -p to chose which hunks to add to stash.

previous top home

Reminder

stash

Save current changes in stash

$ git stash save

Save current changes and untracked files in stash

$ git stash save -u

Chose hunks saved in stash

$ git stash save --patch

Create a stash which ignore staged changes

$ git stash save -keep-index

List stashes

$ git stash list

Show a stash content

$ git stash show stash@{x}

Apply stash to working directory

$ git stash apply
$ git stash apply stash@{x}

Remove stash from stack

$ git stash drop
$ git stash drop stash@{x}

Apply and remove a stash

$ git stash pop
$ git stash pop stash@{x}

Create a branch from stash

$ git stash branch <name>
$ git stash branch <name> stash@{x}
previous top home