epubjs
Version:
Render ePub documents in the browser, across many devices
145 lines (113 loc) • 8.12 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Pro Git - professional version control</title>
<meta content="http://www.w3.org/1999/xhtml; charset=utf-8" http-equiv="Content-Type"/>
<link href="stylesheet.css" type="text/css" rel="stylesheet"/>
<style type="text/css">
@page { margin-bottom: 5.000000pt; margin-top: 5.000000pt; }</style>
</head>
<body class="calibre">
<h2 class="calibre4" id="calibre_pb_51">Stashing</h2>
<p class="calibre3">Often, when you've been working on part of your project, things are in a messy state and you want to switch branches for a bit to work on something else. The problem is, you don't want to do a commit of half-done work just so you can get back to this point later. The answer to this issue is the <code class="calibre10">git stash</code> command.</p>
<p class="calibre3">Stashing takes the dirty state of your working directory - that is, your modified tracked files and staged changes - and saves it on a stack of unfinished changes that you can reapply at any time.</p>
<h3 class="calibre5">Stashing Your Work</h3>
<p class="calibre3">To demonstrate, you'll go into your project and start working on a couple of files and possibly stage one of the changes. If you run <code class="calibre10">git status</code>, you can see your dirty state:</p>
<pre class="calibre9"><code class="calibre10">$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: lib/simplegit.rb
#
</code></pre>
<p class="calibre3">Now you want to switch branches, but you don't want to commit what you've been working on yet; so you'll stash the changes. To push a new stash onto your stack, run <code class="calibre10">git stash</code>:</p>
<pre class="calibre9"><code class="calibre10">$ git stash
Saved working directory and index state \
"WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")
</code></pre>
<p class="calibre3">Your working directory is clean:</p>
<pre class="calibre9"><code class="calibre10">$ git status
# On branch master
nothing to commit (working directory clean)
</code></pre>
<p class="calibre3">At this point, you can easily switch branches and do work elsewhere; your changes are stored on your stack. To see which stashes you've stored, you can use <code class="calibre10">git stash list</code>:</p>
<pre class="calibre9"><code class="calibre10">$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051... Revert "added file_size"
stash@{2}: WIP on master: 21d80a5... added number to log
</code></pre>
<p class="calibre3">In this case, two stashes were done previously, so you have access to three different stashed works. You can reapply the one you just stashed by using the command shown in the help output of the original stash command: <code class="calibre10">git stash apply</code>. If you want to apply one of the older stashes, you can specify it by naming it, like this: <code class="calibre10">git stash apply stash@{2}</code>. If you don't specify a stash, Git assumes the most recent stash and tries to apply it:</p>
<pre class="calibre9"><code class="calibre10">$ git stash apply
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: index.html
# modified: lib/simplegit.rb
#
</code></pre>
<p class="calibre3">You can see that Git re-modifies the files you uncommitted when you saved the stash. In this case, you had a clean working directory when you tried to apply the stash, and you tried to apply it on the same branch you saved it from; but having a clean working directory and applying it on the same branch aren't necessary to successfully apply a stash. You can save a stash on one branch, switch to another branch later, and try to reapply the changes. You can also have modified and uncommitted files in your working directory when you apply a stash - Git gives you merge conflicts if anything no longer applies cleanly.</p>
<p class="calibre3">The changes to your files were reapplied, but the file you staged before wasn't restaged. To do that, you must run the <code class="calibre10">git stash apply</code> command with a <code class="calibre10">--index</code> option to tell the command to try to reapply the staged changes. If you had run that instead, you'd have gotten back to your original position:</p>
<pre class="calibre9"><code class="calibre10">$ git stash apply --index
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: lib/simplegit.rb
#
</code></pre>
<p class="calibre3">The apply option only tries to apply the stashed work - you continue to have it on your stack. To remove it, you can run <code class="calibre10">git stash drop</code> with the name of the stash to remove:</p>
<pre class="calibre9"><code class="calibre10">$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051... Revert "added file_size"
stash@{2}: WIP on master: 21d80a5... added number to log
$ git stash drop stash@{0}
Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
</code></pre>
<p class="calibre3">You can also run <code class="calibre10">git stash pop</code> to apply the stash and then immediately drop it from your stack.</p>
<h3 class="calibre5">Un-applying a Stash</h3>
<p class="calibre3">In some use case scenarios you might want to apply stashed changes, do some work, but then un-apply those changes that originally came form the stash. Git does not provide such a <code class="calibre10">stash unapply</code> command, but it is possible to achieve the effect by simply retrieving the patch associated with a stash and applying it in reverse:</p>
<pre class="calibre9"><code class="calibre10">$ git stash show -p stash@{0} | git apply -R
</code></pre>
<p class="calibre3">Again, if you don't specify a stash, Git assumes the most recent stash:</p>
<pre class="calibre9"><code class="calibre10">$ git stash show -p | git apply -R
</code></pre>
<p class="calibre3">You may want to create an alias and effectively add a <code class="calibre10">stash-unapply</code> command to your git. For example:</p>
<pre class="calibre9"><code class="calibre10">$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash
$ #... work work work
$ git stash-unapply
</code></pre>
<h3 class="calibre5">Creating a Branch from a Stash</h3>
<p class="calibre3">If you stash some work, leave it there for a while, and continue on the branch from which you stashed the work, you may have a problem reapplying the work. If the apply tries to modify a file that you've since modified, you'll get a merge conflict and will have to try to resolve it. If you want an easier way to test the stashed changes again, you can run <code class="calibre10">git stash branch</code>, which creates a new branch for you, checks out the commit you were on when you stashed your work, reapplies your work there, and then drops the stash if it applies successfully:</p>
<pre class="calibre9"><code class="calibre10">$ git stash branch testchanges
Switched to a new branch "testchanges"
# On branch testchanges
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: lib/simplegit.rb
#
Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
</code></pre>
<p class="calibre3">This is a nice shortcut to recover stashed work easily and work on it in a new branch.</p>
</body>
</html>