Git command to save a stash without modifying working tree?

Eliot picture Eliot · Jun 11, 2011 · Viewed 11.4k times · Source

I have been wanting to use a git command that saves a stash without modifying my working tree, as a lightweight backup that's safe from any git resets or whatever I might do to screw up my index. Basically the functional equivalent of "git stash save && git stash apply" except that the working copy is never touched, since this can make certain text editors/IDE's cranky.

Something like this is approaching what I want, but not quite:

git update-ref refs/stash `git stash create "Stash message"`

This works functionally, but the issue I'm having is that no stash message shows up in "git stash list" even though the actual stash commit does have my message in it. Considering how large a stash can get, stash messages are pretty important.

Answer

Eliot picture Eliot · Jun 11, 2011

Thanks to Charles' tip, I whipped up a bash script to do exactly what I wanted (I was running into issues implementing this as only an alias). It takes an optional stash message just like git stash save. If none is supplied it will use the default message generated by git stash.

#!/bin/sh
#
# git-stash-snap
# Save snapshot of working tree into the stash without modifying working tree.
# First argument (optional) is the stash message.
if [ -n "$1" ]; then
        git update-ref -m "$1" refs/stash "$(git stash create \"$1\")"
else
        HASH=`git stash create`
        MESSAGE=`git log --no-walk --pretty="tformat:%-s" "$HASH"`
        git update-ref -m "$MESSAGE" refs/stash "$HASH"
fi

Edit: As pointed out in a comment below, saving this script as git-stash-snap somewhere in your path is sufficient to be able to invoke it by typing git stash-snap.

The nice thing here is that even if you drop a stash made with this method, you will still be able to see the stash message using git log [commit-hash] of the dangling commit!

Edit: since git 2.6.0 you can add --create-reflog to update-ref and then git stash list will show this even if git stash was not used before.

Edit: Git has introduced a new stash subcommand called stash push so I have updated my recommendation for naming this script from git-stash-push to git-stash-snap.