如何重命名git stash?


202

我的藏匿处名称不正确。我想更正这个名字,以便准确。

如何重命名存储?


5
弹出并用其他名称再次保存?
Bartlomiej Lewandowski 2014年

5
再次弹出并隐藏并不总是一种选择,因为隐藏可能基于过时的状态,并在弹出时导致冲突。(过时的状态甚至不必在历史上任何地方都存在。)
汤姆(Tom

Answers:


258

假设您的存储清单如下所示:

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

首先,必须删除要重命名的存储项:

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

现在,只需使用删除后返回的提交sha再次添加新消息即可:

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

就是这样:

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

此解决方案需要git 1.8.4或更高版本,是的,它也适用于脏工作目录。


3
git show stash@{0}之后仍然显示旧信息。如何解决?(请注意,存储区将获得不同的SHA。)
Tino

4
最好使用git show并开始使用哈希git stash store。然后,git stash list您将看到新旧藏匿处。最后,您可以使用清理旧存储git stash drop
hogi'7

6
git stash drop不会丢失更改吗?
Shravya Boggarapu '17

4
@ShravyaBoggarapu,不,git在git gc运行之前不会删除提交。之后,stash drop您可以使用git fsck | grep commit命令轻松找到此通常无法访问的提交。
qzb

2
@ÐerÆndi只是简单地应用和保存是一个简单的选择,但是当由于冲突而无法重新应用更改时,则不起作用。同时,在任何情况下都可以存放和存放作品。我再次测试了我的解决方案-在最新的git版本(2.17.0)上也可以正常工作。
qzb

62

除非您手动进行操作或对Git做出改进,否则可以使用别名:

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}; }; _'

用法:“ git stash-rename <stash> [save options] [<message>]

[save options]任何选项git stash save[-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] [-u|--include-untracked] [-a|--all]

例:

$ 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

即使您进行了本地未暂存的更改,这也将起作用:)

编辑2016/02/22

简化的脚本,感谢qzbhttps: //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; }; _'

用法:“ git stash-rename <stash> [<message>]


1
太棒了!如果可以的话,甚至更凉爽git stash-rename 'tests with deployAtEnd' 'NXP-13971-deployAtEnd'
mikemaccana

3
因此答案是1)干净的工作副本,2)应用要重命名的存储,3)从存储列表中删除它,4)使用正确的消息创建一个新的存储。
gcb 2014年

2
为了澄清起见,您要重命名最后一个存储区,并且在执行此操作后它是否会成为最高级存储区?
onebree

2
我删除存储库以重命名,保存当前更改(如果有的话),用想要的名称重新创建已删除的存储库,如果有的话重新应用当前更改。
Julien Carsique

3
此版本检查以确保两个参数都存在,因此它不会只是意外地丢弃了最后一个存储区。它还仅需要存储号,而不需要整个stash@{0}引用。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

6

非常简单 首先,使用以下命令撤消最后一个存储:

git stash pop

之后,您可以通过以下方式使用自定义名称保存存储:

git stash save "your explanatory name"

希望对您有用。:)


重命名的存储可能不是最新的。
mikemaccana

竖起大拇指,因为这对于最近的藏匿更为直接(唯一)。
开化

3

我认为不可能这样做。有人提出了隐藏存储重命名的建议,但尚未实施。

我的一般想法是:

  1. 实现一个新git reflog update命令,以更新与特定引用日志条目关联的消息。为此,新update_reflog_ent()功能(在reflog.c中)将更改与特定reflog条目关联的消息以进行更新。一个update_reflog()功能将使用for_each_reflog_ent()update_reflog_ent实际做的改变。

  2. git stash rename则命令只需要调用git reflog update与适当的裁判及新讯息。

或者,您当然可以弹出储藏盒并进行 git stash save [message]


3

为了读者的利益,这是对当前接受的正确答案扩展

如果您不仅要更正隐藏消息,而且还想要更正隐藏的提交消息,例如

git stash list

git log --oneline -1 stash

两者都同意显示的内容,您还需要更多。可能会有更好的方法,但是我希望这里的食谱很容易理解。

为此,git commit --amend您需要在分支机构的提示上。因此,解决方案是:

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

解释:

  • 从“有问题的存储区”创建一个新的(尚不存在的)“临时”分支并切换到该分支
  • 删除旧的藏匿处。这很安全,因为我们仍然在分支机构上保留此代码。
  • 使用git commit --amend更换提交信息,这改变了“有问题藏匿”的SHA
  • 根据qzb的答案存储存储
  • 转回(假设您来自“主”)并进行清理

缺点:

  • 这将临时切换分支。因此,此食谱只能在git status --porcelain干净的情况下应用(阅读:不输出任何内容)

  • 它重新编号存储区,因此更改后的存储区变为 stash@{0}

  • 您需要输入$MESSAGE两次或使用一些环境变量(在本例中:MESSAGE

  • 您需要找到一个未使用的分支名称

有多种方法可以执行而无需切换分支,但这超出了此答案的范围。

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

输出量

*-.   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

现在无需更改提交(请注意:下面的SHA在您身边将有所不同):

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

输出量

*-.   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

正如你所看到的,stash@{0}仍然显示为2fbf900 (refs/stash) WIP on master: 8bdcc32 Dgit log。如果仔细看,您会发现一些提交已更改SHA。这是由于存储方式的处理(SHA包含了父级,并且存储项将其存储项作为父项)。

解决:

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

输出量

*-.   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

如您所见,refs/stashSHA也已更改。


值得一提的是:这会破坏用原始存储保存的索引,而用与原始存储的父提交匹配的新索引替换它。如果您不打算使用原始保存的索引(或者它已经与原始存储的父项匹配),那么这不是问题。
torek '19

1

这是Julien别名的修改版本,可让您正确处理On <branch>通常存储在存储名称中的前缀:

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; }; _'

句法:

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

用法示例:

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

大多数命令用于解析参数并确定对分支名称应执行的操作。使用的git工具如下:

  • git rev-parse <stash> 找到隐藏的SHA。
  • git stash list --format=%gs -1 <stash>查找藏匿处的reflog主题。请注意,这与存储的提交消息不同,该消息不会被此命令更改。reflog主题显示在中git stash list,您可以更改reflog主题,而无需更改与隐藏关联的提交的哈希值。但是,您始终可以找到原始的提交消息,因此请不要git stash-rename用来删除敏感信息!
  • git stash drop <stash>删除对存储的旧引用(但我们仍然具有SHA,因此它不会丢失)。
  • git stash store -m <new-message> <sha>用相同的提交信息但reflog主题不同的方式保存对存储的新引用
  • git stash list列出操作完成后的存储。请注意,新存储将始终被推到列表的开头。为了恢复其原始位置,有必要在关注的存储区之前重新推送所有存储区。

0

最简单的方法:使用git stash pop弹出您的存储,然后使用git stash再次保存保存您的名称


重命名的存储可能不是最新的。
mikemaccana
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.