我有一个名称不正确的储藏。我想要修正这个名称,以使其准确。
如何重命名储藏?
我有一个名称不正确的储藏。我想要修正这个名称,以使其准确。
如何重命名储藏?
假设你的储藏清单看起来像这样:
$ 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)
现在使用返回的提交哈希值添加新消息后再次添加它:
$ 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 或更高版本,并且它可以在脏的工作目录下工作。
git show
命令获取哈希值,并使用git stash store
命令开始储藏。然后,通过运行git stash list
命令,您将看到旧的和新的储藏。最后,您可以使用git stash drop
命令清除旧的储藏。 - hogigit gc
之前不会删除提交。在执行stash drop
后,您可以使用git fsck | grep commit
命令轻松找到此通常无法访问的提交。 - qzbgit stash drop stash@{1}
时,我说:“你疯了吗?”但它完美地运行了!谢谢 :) - Positive Navid除非您手动执行或为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
即使您有本地未提交的更改,这也能起作用 :)
简化脚本,感谢qzb,https://dev59.com/Al8e5IYBdhLWcg3wPYlA#35549615
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 <存储> [<消息>]
"
git stash-rename 'tests with deployAtEnd' 'NXP-13971-deployAtEnd'
就更酷了。 - mikemaccanagit 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很简单。首先使用以下命令撤销最后一个“stash”:
git stash pop
完成后,您可以通过以下方式使用自定义名称保存存储:
git stash save "your explanatory name"
我希望它对你有用。:)
git stash apply {N}
,您可以通过 git stash list
找到 {N}
。然后,您可以使用 git stash drop {N+1}
删除旧的存储,因为一旦使用新名称存储更改,索引就会增加。 - kano为了读者的方便,这是当前已被接受且正确答案的扩展。
如果你不仅想更正储藏信息,还想更正储藏的提交信息,使之变成:
git stash list
并且
git log --oneline -1 stash
虽然双方都同意所显示的内容,但还需要更多。也许有更好的方法,但这个教程很容易理解,希望对您有所帮助。
要使用 git commit --amend
命令,需要位于分支的最新提交(TIP)位置。因此解决方案是:
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
替换提交消息,从而更改“目标stash”的SHA。缺点:
这会暂时切换分支。因此,只有在git status --porcelain
干净(即:不会输出任何内容)时才能应用此方法
它会重新编号stashes,因此更改后的stash变为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
如您所见,在git log
中仍然显示stash@{0}
为2fbf900 (refs/stash) WIP on master: 8bdcc32 D
。如果您仔细观察,将会发现有几个提交已更改SHA值。这是由于处理stashes的方式(包括SHA值的父级,以及stashes将其stashes作为父级)所致。
修改方法:
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/stash
的SHA也发生了变化。这里有一些简单的方法,适用于简单情况。例如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}
在简单情况下,这是一个很好且易于操作的技巧。但如果想要修改的stash是一段时间以前或在另一个分支上创建的,那么可能无法干净地应用,这可能会使此技术变得非常麻烦。
使用git stash store
似乎也很简单。只需执行git stash store -m "$msg" $ref
,然后即可进行操作。但这似乎在现代版本的git中不起作用。这可能是因为它会在.git/logs/refs/stash
中创建一个条目,其中包含您的新消息,但不会修改存储在$ref
位置实际提交中的消息,而git stash list
现在显然会显示存储在stash提交中的消息,而不是日志中的消息。
以下是一个示例。我使用⏎
符号将较长的行换行。
$ 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
什么?它仍然有相同的糟糕消息。
$ cat .git/logs/refs/stash
0000000000000000000000000000000000000000 24e1f0aa39ede6e3065dd5c7bbb337af5b2a5d91 ⏎
PDaddy <pdaddy@not-my-real-email-address.com> 1655905366 -0400 good message?
虽然这里有新的消息,但为什么stash list
仍然显示错误的消息呢?
$ 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
24e1f0a
。对于可以从当前分支到达的提交,如果最近的提交是它们,则可以使用git commit --amend
实现,否则可以使用交互式变基。但是24e1f0a
不仅不是我们正在使用的任何分支中最新的提交,而且根本无法从我们的分支到达。它形成了一个独立的类似分支的树的头。 所以我们不希望使用变基操作合并到它上面。
但是,我们可以检出来然后修改它。这很容易做到。
$ # 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
现在我们可以使用git store
将经过重新提交的提交放入暂存列表中。
$ 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
让我们放心,我们不会失去任何东西:
$ 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
看起来唯一的区别在于提交哈希值(预期的)和提交消息(这正是我们想要的)。
现在,我们应该放心地丢弃旧的存储。
$ git stash drop stash@{1}
Dropped stash@{1} (24e1f0aa39ede6e3065dd5c7bbb337af5b2a5d91)
$ git stash list
714d9be - stash@{0} (5 minutes ago) On master: good message!
任务完成!
另请参阅:
Brecht Machiels的答案,使用一个管道命令来更直接地进行修改。虽然较难理解,但它是更快和更直接的解决方案,因为它不需要隐藏任何可能存在的挂起更改并检出不同的HEAD。
这种方法唯一的缺点是它会创建一个新的提交,从而改变了日期,并在列表中更改了stash的位置和其reflog选择器(重命名的stash变成stash@{0}
)。
下面是一个神奇的单行代码(为了可读性而分成多行),可以完成Brecht Machiels的方法:
_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"
)
#!/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
git stash store
方法在qzb的回答中描述, 只更新了两个地方之一中的stash消息,导致许多Git前端仍显示旧消息。但是,可以创建一个新提交(commit),它复制了原始stash提交的所有内容但更改了其消息。
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
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
Store this commit as a new stash
$ git stash store \
-m "$(git show -s --format=%B f2adfc7bbebe852693ad8f6ac889e4923230c872)" \
f2adfc7bbebe852693ad8f6ac889e4923230c872
--keep-index
创建的贮藏将有3个父级,因此在这种情况下,您需要向git-commit-tree提供第三个父级!git stash list
现在使用git stash apply {N}
来应用它,例如:
git stash apply 2
现在您可以使用新消息隐藏更改
git stash push -m 'My descriptive stash message'
如果你想清理原始存储库,请记得将索引值增加1,因为新的存储库会递增所有现有索引值(所以我们要使用 N + 1
)。
git stash drop 3
git reflog update
命令,用于更新与特定reflog条目相关联的消息。为此,在reflog.c中创建一个新的update_reflog_ent()
函数,会更改与要更新的特定reflog条目相关联的消息。一个update_reflog()
函数将使用for_each_reflog_ent()
和update_reflog_ent
来实际进行更改。git stash rename
命令只需要调用适当的ref和新消息的git reflog update
。git stash save [message]
。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
命令在操作完成后列出存储区。请注意,新的存储区始终推送到列表的开头。为了恢复其原始位置,需要重新推送所有感兴趣的存储区之前的所有存储区。