How To: Git "drafts"
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.
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}