4

As far as I know Git can not delete a stash by name/message (despite it can save it by name with git stash save "name"). However, I really like to have this option for a 'combined alias' that I want to create for my workflow (especially for colleagues that are not that familiar with git and should respect the workflow)

I know I can create a bash script myself but I was thinking maybe someone already has made such a script!? So that I can delete a stash by name...

My "update" alias is roughly like this:

git stash save -u "tempstash"
git fetch origin
[apply our workflow/update strategy]
git stash pop --index (should be: git stash delete "tempstash")

The problem with the current alias is that if there is nothing to stash, it will restore an old stash.

An other option would be to check if stashing is needed but I always wanted a git stash delete by name option so thats why im asking this.

PS: im using posh-git but bash commands should work within an alias.

Thanks

Alexis King
  • 43,109
  • 15
  • 131
  • 205
GerjanOnline
  • 1,871
  • 16
  • 17

4 Answers4

2

You can overcome the problem with checking whether there is anything to stash first. You can use one of the ways to check whether an index is dirty that are suggested in Checking for a dirty index or untracked files with Git

For instance this command will not output anything if there are no changes to stash:

git status --porcelain

Using this command, the script may look like this:

is_stashing=$(git status --porcelain)
test -n "$is_stashing" && git stash save -u
git fetch origin
[apply our workflow/update strategy]
test -n "$is_stashing" && git stash pop --index
Community
  • 1
  • 1
Sergey Evstifeev
  • 4,941
  • 2
  • 24
  • 28
2

I found a way to drop a stash by name. You can do it like this:

git stash drop stash@{$((git stash list | grep -w NAME_OF_THE_STASH) | cut -d "{" -f2 | cut -d "}" -f1)}

Here is the breakdown of the script:

  1. I am using the standard git stash drop stash@{n} structure
  2. We need to get the n of the stash with the name you want to delete. So to do that we list the stashes and grep the item with the matching name. To do that I used the script: git stash list | grep -w NAME_OF_THE_STASH
  3. Out of that item we need to extract the index which is within brackets {}. We can extract that number by adding to the script in item 2 the following: | cut -d "{" -f2 | cut -d "}" -f1

I tested it and it works great for me.

By the way, if you enter a name that does not exist then nothing gets erased.

Also, only the exact name match will be erased. If you don't want an exact match necessarily then remove the -w after grep.

Eyal Gerber
  • 1,026
  • 10
  • 27
  • Thanks, I adapted the command for when there are several stashes with the same name: it returned "Too many revisions specified": https://stackoverflow.com/a/76604077/358532 – Yann Dìnendal Jul 03 '23 at 10:56
1

A solution would be to search the git reflog stash using the name of the stash as a regexp and obtaining its name in the stash@{<number>} format.

Then you can create an alias in git for using it as a command. A quick and dirty solution, that can be greatly improved, is something like:

[alias]
   sshow = "!f() { git stash show `git reflog stash | egrep $* | awk '{printf $2}' | sed 's/://' `; }; f"
   ssdrop = "!f() { git stash drop `git reflog stash | egrep $* | awk '{printf $2}' | sed 's/://' `; }; f"

By adding this two aliases in your .git/config you can see the files modified in the stash with:

git sshow <regexp matching the name of the stash>

and you can drop the stash with:

git ssdrop <regexp matching the name of the stash>
Atropo
  • 12,231
  • 6
  • 49
  • 62
  • 1
    I like the idea but as you said it should be improved because when there is no match it just picks the last stash, which is, obviously, dangerous – GerjanOnline Dec 23 '13 at 15:28
0

A solution base on the one by @eyal-gerber:

if there are more than one result, the command didn't work, wo we need to keep only the first (or last) result. And loop or run it several times.

For example, to clean the last stash named lint-staged automatic backup:

git stash drop stash@{$((git stash list | grep -w "lint-staged automatic backup" | tail -n1) | cut -d "{" -f2 | cut -d "}" -f1)}

And run this until there are no more (in which case it will not drop any stash, just print an error.

Yann Dìnendal
  • 1,422
  • 2
  • 17
  • 27