How can I rename a git stash?

GitGit Stash

Git Problem Overview


I have a stash with an incorrect name. I would like to fix the name so it's accurate.

How can I rename a stash?

Git Solutions


Solution 1 - Git

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.

Solution 2 - Git

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>]"

Solution 3 - Git

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. :)

Solution 4 - Git

I don't think it is possible to do so. There has been a proposal for stash renaming, but it has not been implemented yet.

> My general idea is:

> 1. Implement a new git reflog update command that updates the message associated with a specific reflog entry. To do this, a new update_reflog_ent() function (in reflog.c) would change the message associated with the specific reflog entry to update. An update_reflog() function would use for_each_reflog_ent() with update_reflog_ent to actually do the change.

> 2. A git stash rename command would then only need to call git reflog update with the appropriate ref and new message.

Or you could, of course, pop the stash and do a git stash save [message]

Solution 5 - Git

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.

Solution 6 - Git

Answering my own question many years later: this just got announced, so thought I'd add it here.

A number of GUI git clients (eg, Fork 1.58 and newer) now support direct renames of stashes.

enter image description here

Solution 7 - Git

The method described in the accepted answer only updates the stash message in one of two places, causing many git frontends to still show the old message. It is however possible to create a commit that duplicates everything from the original stash commit but changes its message.

  1. Find the hashes for the stash commit's tree and parents:

    $ git show -s --pretty=raw stash@{0}
    commit f2adfc7bbebe852693ad8f6ac889e4923230c872
    tree 8160d88c6e00e90fcfa183e09d2563f3cdfb304b
    parent a013bd8052d3260fbc95608ed69d0b9cfa0c77cb
    parent 5d5eb80dc03bea8ff2bdd38962a1259b7725d169
    author ...
    committer ...
    
        Test stash
    
  2. Create a new commit with the same tree and parents but a different message:

    $ git commit-tree 8160d88c6e00e90fcfa183e09d2563f3cdfb304b \
      -p a013bd8052d3260fbc95608ed69d0b9cfa0c77cb \
      -p 5d5eb80dc03bea8ff2bdd38962a1259b7725d169 \
      -m "Renamed stash"
    f2adfc7bbebe852693ad8f6ac889e4923230c872
    
  3. Store this commit as a new stash

    $ git stash store \
      -m "$(git show -s --format=%B f2adfc7bbebe852693ad8f6ac889e4923230c872)" \
      f2adfc7bbebe852693ad8f6ac889e4923230c872
    

The new stash message needs to be supplied to both git-commit-tree and git-stash-store because git stores it in two places (the commit and logs/refs/stash).

Note that stashes created with --keep-index will have 3 parents, so you'll need to supply the third parent to git-commit-tree in that case!

Transforming this procedure into a one-liner for use in a git alias is left as an exercise to the reader ;-). Be sure to use only plumbing commands for this (so avoid e.g. git-show and git-log).

Solution 8 - Git

Here is a modified version of Julien's alias that lets you properly deal with the On <branch> prefix usually prepended to stash names:

git config --global alias.stash-rename '!_() { newmsg="$1" && stash=${2:-"stash@{0}"} && newbranch="$3" && sha=$(git rev-parse "$stash") && olddesc="$(git stash list --format=%gs -1 "$stash")" && newdesc="$(if [[ "$newbranch" = "." ]]; then echo "$newmsg"; else if [[ -n "$newbranch" ]]; then echo "On $newbranch: $newmsg"; else if [[ "$olddesc" =~ ":" ]]; then echo "$(echo "$olddesc" | cut -f1 -d":"): $newmsg"; else echo "$newmsg"; fi; fi; fi)" && git stash drop "$stash" > /dev/null || exit 1; git stash store -m "$newdesc" "$sha" && git stash list; }; _'

Syntax:

git stash-rename <new-name> [<stash> [<new-branch-name> | .]]

Example usage:

repo[master] % touch tmp && git add tmp && git stash save first
Saved working directory and index state On master: first
HEAD is now at bd62064 Initial commit
repo[master] % touch tmp && git add tmp && git stash save second
Saved working directory and index state On master: second
HEAD is now at bd62064 Initial commit
repo[master] % git stash list
stash@{0}: On master: second
stash@{1}: On master: first
repo[master] % git stash-rename renamed
stash@{0}: On master: renamed
stash@{1}: On master: first
repo[master] % git stash-rename also-renamed stash@{1}
stash@{0}: On master: also-renamed
stash@{1}: On master: renamed
repo[master] % git stash-rename branch-changed stash@{0} new-branch
stash@{0}: On new-branch: branch-changed
stash@{1}: On master: renamed
repo[master] % git stash-rename branch-name-persists
stash@{0}: On new-branch: branch-name-persists
stash@{1}: On master: renamed
repo[master] % git stash-rename no-branch stash@{0} .
stash@{0}: no-branch
stash@{1}: On master: renamed
repo[master] % git stash-rename renamed
stash@{0}: renamed
stash@{1}: On master: renamed
repo[master] % git stash-rename readd-branch stash@{0} develop
stash@{0}: On develop: readd-branch
stash@{1}: On master: renamed

Most of the command is for parsing the arguments and figuring out what should be done to the branch name. The git tools used are as follows:

  • git rev-parse <stash> to find the SHA of the stash.

  • git stash list --format=%gs -1 <stash> to find the reflog subject of the stash. Note that this is different from the commit message of the stash, which is not changed by this command. The reflog subject is what shows up in git stash list, and you can change the reflog subject without changing the hashes of the commits associated with the stashes. However, you can always find the original commit message, so don't use git stash-rename to remove sensitive information!

  • git stash drop <stash> to drop the old reference to the stash (but we still have the SHA, so it's not lost).

  • git stash store -m <new-message> <sha> to save a new reference to the stash with the same commit information but a different reflog subject.

  • git stash list to list the stashes after the operation is finished. Note that new stashes are always pushed to the beginning of the list. It would be necessary to re-push all the stashes before the stash of interest in order to restore its original position.

Solution 9 - Git

A lot of complex answers here. I would approach it this way:

First let's find the index of your stash:

git stash list

Now apply it with git stash apply {N}, for example

git stash apply 2

You can now stash the changes with a new message

git stash push -m 'My descriptive stash message'

And if you'd like to clean up the original stash, remember to bump the index by 1, since the new stash increments all existing indexes (so we're going for N + 1 here)

git stash drop 3

Solution 10 - Git

Simplest way: pop your stash with git stash pop then save it again with git stash save your-name

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmikemaccanaView Question on Stackoverflow
Solution 1 - GitqzbView Answer on Stackoverflow
Solution 2 - GitJulien CarsiqueView Answer on Stackoverflow
Solution 3 - GitSandraView Answer on Stackoverflow
Solution 4 - GitA1ternat1veView Answer on Stackoverflow
Solution 5 - GitTinoView Answer on Stackoverflow
Solution 6 - GitmikemaccanaView Answer on Stackoverflow
Solution 7 - GitBrecht MachielsView Answer on Stackoverflow
Solution 8 - GitRadon RosboroughView Answer on Stackoverflow
Solution 9 - GitkanoView Answer on Stackoverflow
Solution 10 - Gityoel neumanView Answer on Stackoverflow