308

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?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • 5
    pop it and save it again with a different name? – Bartlomiej Lewandowski Sep 19 '14 at 11:54
  • 10
    Popping and stashing again isn't always an option, because the stash might be based on outdated state and result in conflicts when popping. (The outdated state does not even have to exist anywhere in the history anymore.) – Tom Nov 09 '18 at 11:58
  • 1
    You might be interested in a slightly different workflow: just create a new branch from the stash entry. Something like: git branch stash/myNewName stash@{13} creates a new branch that has a head commit of the 13th entry in your stash list. – James Moore Sep 03 '21 at 14:54
  • @JamesMoore you should add that as an answer! I’ll upvote it. – mikemaccana Sep 07 '21 at 14:12

11 Answers11

386

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.

qzb
  • 8,163
  • 3
  • 21
  • 27
  • 1
    You meant `git stash store`. Indeed, it's a good improvement which avoids dealing with current changes. I'm updating my answer. – Julien Carsique Feb 22 '16 at 10:54
  • 4
    `git show stash@{0}` still shows the old information afterwards. How to fix that? (Please note that the stash then gets a different SHA.) – Tino Mar 08 '17 at 11:15
  • 27
    It feels better to get the hash with `git show` and start with `git stash store`. Then with `git stash list` you will see the old and the new stash. Finally you can clean-up the old stash with `git stash drop`. – hogi Jul 05 '17 at 06:44
  • 19
    will git stash drop not lose the changes? – Shravya Boggarapu Jul 21 '17 at 13:27
  • 14
    @ShravyaBoggarapu, no, git doesn't remove commit until `git gc` is run. After `stash drop` you can easily find this normally inaccessible commit using `git fsck | grep commit` command. – qzb Jul 21 '17 at 14:14
  • I always get a message `"git stash store" requires one argument`, even if I do a git stash store before. I applied the concerned stash and did another `git stash save [label]`, which should be the easiest approach, in my opinion... – ÐerÆndi Apr 17 '18 at 06:35
  • 6
    @ÐerÆndi simply applying and saving is an easy option, but doesn't work when changes cannot be re-applied due to conflicts. Meanwhile dropping and storing works under any circumstances. I've tested my solution once again - it works just fine on latest git version (2.17.0). – qzb Apr 17 '18 at 13:11
  • @JulienCarsique `git stash store -m …` and not just `git stash -m …` because the former can take a commit? – Geremia Dec 19 '18 at 00:18
  • 4
    I said: "Are you insane?" when I read: `git stash drop stash@{1}` But it worked perfectly! Thanks :) – Positive Navid Mar 19 '20 at 23:46
  • 1
    After doing this, `git stash apply` gives me `fatal: 'refs/stash@{0}' is not a stash-like commit`? – lmm Dec 23 '20 at 05:26
  • @hogi storing the renamed copy of the stash before dropping the original is somehow not working for me had to drop first, save afterwards – sumek Dec 15 '21 at 15:33
  • thanks for pointing out `git stash store`! it wasn't listed in the short-help of `git stash -h` so it was harder to find. worth mentioning that you _do_ need to drop first before storing the new one, as otherwise it doesn't show up for whatever reason – starwarswii Sep 13 '22 at 17:33
  • I suggest `git stash push -m "message"` as the [current doc 2.38.1 for git stash store](https://git-scm.com/docs/git-stash#Documentation/git-stash.txt-store) say: _Store a given stash created via git stash create (which is a dangling merge commit) in the stash ref, updating the stash reflog. This is intended to be useful for scripts._ – Dwhitz Oct 26 '22 at 15:33
  • 1
    @PositiveNavid you can also use the short version `git stash drop 1` – Dwhitz Oct 26 '22 at 15:35
79

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

Community
  • 1
  • 1
Julien Carsique
  • 3,915
  • 3
  • 22
  • 28
  • 2
    Awesome! Even cooler if you could do `git stash-rename 'tests with deployAtEnd' 'NXP-13971-deployAtEnd'` – mikemaccana Sep 19 '14 at 14:27
  • 1
    @mikemaccana Easy with grep+awk. I'll update the answer in a few hours. – Julien Carsique Sep 19 '14 at 14:49
  • 1
    This one is the better answer. +1 from me. – A1ternat1ve Sep 20 '14 at 13:53
  • 4
    so the answer is 1) clean working copy, 2) apply stash you want to rename, 3) drop it from stash list, 4) create a new stash with the correct message. – gcb Dec 03 '14 at 23:20
  • 2
    To clarify, you are renaming the last stash, and after such action it becomes the top stash? – onebree Apr 20 '15 at 14:05
  • 2
    I delete the stash to rename, save current changes if any, recreate the deleted stash with the wanted name, reapply current changes if any. – Julien Carsique Apr 20 '15 at 22:33
  • 1
    Is this method 100% safe? – danihodovic Jun 17 '15 at 13:16
  • @dani-h I think so since Git stores patches for a while until GC and I save the current changes if any. – Julien Carsique Jun 17 '15 at 19:32
  • 1
    I actually stumbled across an issue in the case that the "stash apply" step experiences a merge conflict. Now, one of the other stashes has gotten renamed to the temp name. But the rest of the steps after the "stash apply" seemed to work OK when I executed them one at a time manually. – Al Chou Dec 01 '15 at 00:50
  • 1
    @dani-h No. because git version < 1.8.4 does not have `git stash store` (for example, default on centos 7) and you will lose stash, "nice"! – catpnosis Mar 07 '16 at 00:19
  • @catpnosis First version (before edit) does not use the store command. – Julien Carsique Mar 07 '16 at 00:40
  • second version should stop if no parameters are given; instead, it drops then first stash then exits... – Stefano Aug 23 '17 at 09:41
  • thanks @mikemaccana; it's one-lined because that's the usage for Git aliases. Actually, I just tried in multi-line and it does not register properly in `~/.gitconfig` – Julien Carsique Nov 23 '18 at 09:39
  • @JulienCarsique is it possible to use an external file? – mikemaccana Nov 23 '18 at 11:56
  • 7
    This version checks to make sure both arguments are there so it doesn't just drop your last stash accidentally. It also only requires the stash number, not the whole `stash@{0}` reference. https://gist.github.com/jdforsythe/f248bf6c72fc020225cc3e315a32e922 `git config --global alias.stash-rename '!_() { if [ -z \"$1\" ] || [ -z \"$2\" ]; then echo \"git stash-rename 0 NewName\" && echo \"\" && git stash list && exit 1; else stash=\"stash@{$1}\"; rev=$(git rev-parse \"${stash}\"); git stash drop \"${stash}\" || exit 1; git stash store -m \"$2\" \"$rev\" || exit 1; git stash list; fi }; _'` – jdforsythe Mar 13 '19 at 15:33
  • Not sure if this is just a zsh problem, but anyone else getting? `fatal: ambiguous argument 'stash@0': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git [...] -- [...]'` – ahong Nov 06 '20 at 11:47
  • 2
    Be careful with this version of the script (shown in the answer): `git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git stash store -m "$2" $rev; }; _'`. If it's called without arguments, it drops the stash at "refs/stash@{0}". It can be recovered with a command like `git stash store -m 'descriptive message' hash…here`, where the hash is the one shown when git dropped the stash. – Mr. Lance E Sloan Oct 14 '21 at 15:26
  • 1
    The alias by @jdforsythe in the [comment above](https://stackoverflow.com/questions/25931026/how-can-i-rename-a-git-stash#comment97031938_25935360) only worked for me when I removed the escaping from all of the double quotes (i.e., `\"` → `"`). I'm using bash, FWIW. – Mr. Lance E Sloan Oct 14 '21 at 15:38
14

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

Sandra
  • 358
  • 3
  • 5
  • 15
    The renamed stash may not be the most recent. – mikemaccana Mar 28 '19 at 13:53
  • Thumbs up since this more straightforward (ONLY) for the most recent stash . – Kaihua Feb 03 '20 at 15:14
  • 1
    If it's not the most recent stash, simply do `git stash apply {N}`, you can find `{N}` via `git stash list`. And then you can remove the old stash with `git stash drop {N+1}`, because the index will get bumped once you stash the changes with a new name. https://stackoverflow.com/a/67017993/2803743 – kano Apr 09 '21 at 08:48
6

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.

Tino
  • 9,583
  • 5
  • 55
  • 60
  • 1
    Worth mention: this destroys the index that was saved with the original stash, replacing it with a new index that matches the parent commit of the original stash. If one wasn't planning to use the original saved index (or it already matched the parent of the original stash), this is not a problem. – torek Jun 01 '19 at 20:17
5

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

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • 6
    For those wondering, [Fork employs](https://github.com/fork-dev/Tracker/issues/218#issuecomment-756692030) the approach described in [my answer](https://stackoverflow.com/a/65627640/438249). – Brecht Machiels Jan 21 '21 at 13:02
4

The git stash store-method described in qzb's 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).

Brecht Machiels
  • 3,181
  • 3
  • 25
  • 38
  • 2
    Given that the asker can change which answer is _accepted_ at any time, perhaps you need to more stable identifier in your first sentence. Are you referring to [qzb's answer](/a/35549615/4850040)? – Toby Speight Jul 26 '22 at 07:01
4

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
kano
  • 5,626
  • 3
  • 33
  • 48
4

There are some simple approaches here, which work in simple cases. Such as git stash apply:

$ # Stash any pending changes you have, if applicable.
$ git stash -um "temporary stash"
$ # Re-apply the stashed changes whose message you want to change.
$ git stash apply stash@{1}
$ # Now stash again with the message you want.
$ git stash push -um "good message"
$ # Now you can pop your temporary stash and drop your poorly named one.
$ git stash pop
$ git stash drop stash@{1}

That's a great, easy technique in simple cases. But if the stash you want to reword was made some time ago, or on a different branch, it might not apply cleanly, and that can make this technique a major pain.

Using git stash store also seems easy. Just git stash store -m "$msg" $ref, and off you go. But that doesn't seem to work with modern versions of git. Probably because this creates an entry in .git/logs/refs/stash containing your new message, but doesn't modify the message stored in the actual commit at $ref, and git stash list apparently now displays the messages stored in the stash commits, as opposed to the ones in the log.

Here's an example. I wrapped long lines with a symbol.

$ git init
$ touch foo
$ git add foo
$ git commit -m foo foo
[master (root-commit) a839f24] foo
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foo

$ git stash push -m "bad message"
Saved working directory and index state On master: bad message

$ git stash list
24e1f0a - stash@{0} (4 seconds ago) On master: bad message

$ cat .git/logs/refs/stash
0000000000000000000000000000000000000000 24e1f0aa39ede6e3065dd5c7bbb337af5b2a5d91 ⏎
PDaddy <pdaddy@not-my-real-email-address.com> 1655905352 -0400 bad message

$ git stash drop
Dropped refs/stash@{0} (24e1f0aa39ede6e3065dd5c7bbb337af5b2a5d91)

$ git stash store -m "good message?" 24e1f0a
$ git stash list
24e1f0a - stash@{0} (16 seconds ago) On master: bad message

What? It still has the same bad message.

$ cat .git/logs/refs/stash
0000000000000000000000000000000000000000 24e1f0aa39ede6e3065dd5c7bbb337af5b2a5d91 ⏎
PDaddy <pdaddy@not-my-real-email-address.com> 1655905366 -0400 good message?

It has the new message there, though. So why does stash list still show the bad message?

$ git show stash@{0}
Merge: a839f24 7b91532
Author: PDaddy <pdaddy@not-my-real-email-address.com>
Date:   Wed Jun 22 09:40:27 2022 -0400

    On master: bad message

diff --cc foo
index e69de29,e69de29..d1d375f
--- a/foo
+++ b/foo
@@@ -1,0 -1,0 +1,1 @@@
++Wed Jun 22 09:40:21 AM EDT 2022

You can see that the bad message is still part of the metadata of the actual commit, which we didn't modify. Doing so requires replacing commit 24e1f0a with a new commit. For commits that are reachable from our current branch, we can do that with git commit --amend, if it's the most recent commit, or with an interactive rebase, otherwise. But 24e1f0a is not only not the most recent commit in whatever branch we're using, it's not reachable at all from our branch. It forms the head of an independent branch-like tree. So we wouldn't want to rebase onto it.

But we can check it out and then modify it. It's pretty easy to do so.

$ # If we have any pending changes, stash them first.
$ git stash -um "temporary stash before rewording another stash commit"
Saved working directory and index state On master: temporary stash...

$ git checkout 24e1f0a
Note: switching to '24e1f0a'.

You are in 'detached HEAD' state.
...snip: protracted warning message
HEAD is now at 24e1f0a On master: bad message

$ git commit --amend -m 'On master: good message!'
[detached HEAD 714d9be] On master: good message!
 Date: Wed Jun 22 09:40:27 2022 -0400

$ git switch -
Warning: you are leaving 2 commits behind, not connected to
any of your branches:

  714d9be On master: good message!
  7b91532 index on master: a839f24 foo

If you want to keep them by creating a new branch, this may be a good time
to do so with:

 git branch <new-branch-name> 714d9be

Switched to branch 'master'

$ # If we made a temporary stash earlier, pop it now.
$ git stash pop
blah blah blah

Now we can use git store to put our reworded commit into the stash list.

$ git stash store -m 'On master: good message!' 714d9be
$ git stash list
714d9be - stash@{0} (2 minutes ago) On master: good message!
24e1f0a - stash@{1} (10 minutes ago) On master: bad message

Let's put our minds at ease that we're not losing anything:

$ git merge-tree @ stash@{0} stash@{1}
$ # No output is good.  But if we're still not certain...
$ diff <(git show stash@{0}) <(git show stash@{1})
1c1
< commit 714d9be27dee44e96ddd3c5a4a43b35cff34a4cc
---
> commit 24e1f0aa39ede6e3065dd5c7bbb337af5b2a5d91
6c6
<     On master: good message!
---
>     On master: bad message

Looks like the only differences are the commit hashes (expected) and the commit messages (that's what we wanted).

So now, we should feel comfortable dropping the old stash.

$ git stash drop stash@{1}
Dropped stash@{1} (24e1f0aa39ede6e3065dd5c7bbb337af5b2a5d91)

$ git stash list
714d9be - stash@{0} (5 minutes ago) On master: good message!

Mission accomplished!


See also:

  • Tino's answer, which uses a similar technique, but creates a temporary branch instead of using a detached head

  • Brecht Machiels's answer, which uses a plumbing command to make the change more directly. It's harder to understand, but it's a faster and more straightforward solution, since it doesn't require stashing any pending changes you might have and checking out a different HEAD.

    The one drawback to this method is that because it creates a new commit, it changes the date, and thus the stash's position in the list and its reflog selector (the renamed stash becomes stash@{0}).

Here's a magic one-liner (but broken up to multiple lines for readability) to accomplish Brecht Machiels's method:

_commit=$(git stash drop ${stash:-0} | sed -Ee 's/Dropped.+\((.+)\)$/\1/') &&
git stash store -m "$msg" $(
    git commit-tree $(
        git show -s --pretty=%T\ %P $_commit |
        sed -Ee 's/ / -p /g'
    ) -m "$msg"
)

Note that this depends on the shell word splitting the output of the inner command substitution.

Here's a more readable script.

#!/bin/bash

message=$1
stash=${2:-0}
commit=$(
    git stash drop $stash 2>/dev/null |
    sed -nEe 's/Dropped.+\((.+)\)$/\1/p'
)

if [[ -z $message || -z $commit ]]; then
    echo >&2 "usage: $(basename "$0") MESSAGE [STASH]"
    exit 1
fi

args=(
    # Suppress diff output.
    --no-patch
    # Get the tree hash and the hashes of all the parents.
    --pretty=%T\ %P
)
refs=$(git show "${args[@]}" $commit)

# Format the refs as arguments to `git commit-tree` by inserting "-p" in front of
# each of the parent hashes and then splitting on spaces to separate arguments.
args=($(sed -Ee 's/ / -p /g' <<< "$refs"))

# Create a new commit with the same tree and parents as the old stash, but with
# the new message.
new_commit=$(git commit-tree "${args[@]}" -m "$message")

# Store the new commit in the stash.
git stash store -m "$message" $new_commit
P Daddy
  • 28,912
  • 9
  • 68
  • 92
3

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]

Michael
  • 8,362
  • 6
  • 61
  • 88
1

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.
Community
  • 1
  • 1
Resigned June 2023
  • 4,638
  • 3
  • 38
  • 49
0

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

yoel neuman
  • 133
  • 7
  • 1
    The renamed stash may not be the most recent. – mikemaccana Mar 28 '19 at 13:54
  • @mikemaccana True, but this was still super useful in my case because it was the latest stash, and this means I can skip most of the overly advanced answers here – anaotha Sep 26 '22 at 10:59