How can I rename a git stash?

Unless you do it manually or contribute an improvement to Git, you can use an alias:

git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git diff-index --quiet HEAD; s=$?; [ $s != 0 ] && git stash save "tmp stash from stash-rename"; git stash apply $rev && shift && git stash save "$@" && [ $s != 0 ] && git stash pop stash@{1}; }; _'

Usage: "git stash-rename <stash> [save options] [<message>]"

With [save options] any option of git stash save: [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] [-u|--include-untracked] [-a|--all]

Example:

$ git stash list
stash@{0}: On master: Pep8 format
stash@{1}: On master: co other than master with local changes
stash@{2}: On master: tests with deployAtEnd

# Let's say I want to rename the stash@{2} adding an issue reference:
$ git stash-rename stash@{2} NXP-13971-deployAtEnd

$ git stash list
stash@{0}: On master: NXP-13971-deployAtEnd
stash@{1}: On master: Pep8 format
stash@{2}: On master: co other than master with local changes

That will work even if you have local unstaged changes :)

EDIT 2016/02/22

Simplified script, credits to qzb, https://stackoverflow.com/a/35549615/515973

git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git stash store -m "$2" $rev; }; _'

Usage: "git stash-rename <stash> [<message>]"


For the benefit of the reader, here is an extension to the currently accepted and correct answer.

If you not only want to correct the stash message and also want to correct the commit message of the stash, such that

git stash list

and

git log --oneline -1 stash

both agree to what is shown, you need a bit more. There might be a better way to do it, but this recipe here is easy to understand, I hope.

To be able to do git commit --amend you need to be on the TIP of a branch. Hence the solution is:

git checkout -b scratch stash@{1}
git stash drop stash@{1}
git commit --amend -m "$MESSAGE"
git stash store -m "$MESSAGE" HEAD
git checkout master
git branch -D scratch

Explained:

  • Create a new (not yet existing) "scratch" branch from the "stash in question" and switch to it
  • Remove the old stash. This is safe, as we still have this on the branch.
  • Use git commit --amend to replace the commit message, this changing the SHA of the "stash in question"
  • Store the stash, based on the qzb's answer
  • Switch back (which assumes you came from "master") and cleanup

Drawbacks:

  • This switches branches temporarily. So this recipe can only be applied when git status --porcelain is clean (read: does not output anything)

  • It renumbers the stashes, so the changed stash becomes stash@{0}

  • You need to enter the $MESSAGE twice or use some environment variable (in the example: MESSAGE)

  • You need to find an unused branch name

There are ways to do this without switching branches, but this is beyond the scope of this answer.

Example

git init scratch
cd scratch
for a in A B C D; do date >$a; git add $a; git commit -m $a; done
for a in X Y; do echo $a > Z; git stash save --all; done
git log --oneline --graph --decorate --all; git stash list

Output

*-.   e0e281b (refs/stash) WIP on master: 8bdcc32 D
|\ \  
| | * 4d62f52 untracked files on master: 8bdcc32 D
| * 096f158 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: WIP on master: 8bdcc32 D
stash@{1}: WIP on master: 8bdcc32 D

Now without changing commit (note: the SHA in following will be different at your side):

git stash drop stash@{1}
git stash store -m ...changed... 2fbf9007dfdfb95ae269a19e13b8b9ca3e24181c
git log --oneline --graph --decorate --all; git stash list

Output

*-.   2fbf900 (refs/stash) WIP on master: 8bdcc32 D
|\ \  
| | * 246dc5c untracked files on master: 8bdcc32 D
| * 80c5ea0 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: ...changed...
stash@{1}: WIP on master: 8bdcc32 D

As you can see, stash@{0} still is shown as 2fbf900 (refs/stash) WIP on master: 8bdcc32 D in git log. If you look carefully, you will see, that several commits have changed SHA. This is due to how stashes are handled (parents are included of the SHA, and stashes have their stashes as parent).

Fix that:

git checkout -b scratch stash
git stash drop
git commit --amend -m ...changed...
git stash store -m ...changed... HEAD
git checkout master
git branch -D scratch
git log --oneline --graph --decorate --all; git stash list

Output

*-.   4d55186 (refs/stash) ...changed...
|\ \  
| | * 246dc5c untracked files on master: 8bdcc32 D
| * 80c5ea0 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: ...changed...
stash@{1}: WIP on master: 8bdcc32 D

As you also can see, refs/stash has a changed SHA, too.


It's very simple. First, undo the last stash with:

git stash pop

After this, yo can save the stash with a customized name in this way:

git stash save "your explanatory name"

I hope it useful for you. :)


Let's assume your stash list looks like this:

$ git stash list
stash@{0}: WIP on master: Add some very important feature 
stash@{1}: WIP on master: Fix some silly bug

First, you must remove stash entry which you want to rename:

$ git stash drop stash@{1}
Dropped stash@{1} (af8fdeee49a03d1b4609f294635e7f0d622e03db)

Now just add it again with new message using sha of commit returned after dropping:

$ git stash store -m "Very descriptive message" af8fdeee49a03d1b4609f294635e7f0d622e03db

And that's it:

$ git stash list
stash@{0}: Very descriptive message
stash@{1}: WIP on master: Add some very important feature

This solution requires git 1.8.4 or later, and yes, it works with dirty working directory too.

Tags:

Git

Git Stash