假设我过快地将一个藏匿在git中并且没有提供信息性的藏匿消息。我想修改存储中的消息,但无法从git文档中找到一种方法。我可以让repo进入一个干净的状态然后弹出存储并重新应用w / git stash保存“我的保存消息”但是想知道是否有人有解决方案来修改消息。
答案 0 :(得分:3)
这在技术上是不可能的,但很容易通过欺骗来实现预期的目标。即使git commit
具有--amend
选项,Git也没有任何内置机制来完成诡计。 (也没有干净的方法可以劫持git commit --amend
。)
最后,你必须做你所建议的事情。如果你愿意的话,你可以在脚本中隐藏它,但对于一次性案例来说,除了手工操作之外,还有更多的工作。
在Git命令行命令和选项等的掩护下,Git存储条目实际上是提交。更准确地说,它至少提交了两次,有时是三次。 The git stash
documentation在标记为DISCUSSION的部分中描述了这一点(相当轻松和粗心),使git stash
提交特殊内容的事情是它们位于 no 分支上,并且,集群中的w
(工作树)提交(refs/stash
引用所在的提交)具有合并提交的形式,因此它可以列出多个父提交ID。我更喜欢把它们画成:
...--F--G <-- branch
|\
i-w <-- (the stash)
或:
...--F--G <-- branch
|\
i-w <-- (the stash)
/
u
与Git文档绘图略有不同,但显示了我称之为 stash bag (带有未跟踪文件的可选u
提交)从你保管时的当前提交中摇晃出来。 (如果你尚未将HEAD
移动到其他位置,那么提交仍然当前提交。)这里的大写字母代表实际的提交哈希值,这些哈希值很大,很难看,也不可能记住。
与所有提交一样,特殊的存储提交是只读的 - 它们永远不会被更改,它们只能忘记它们的哈希ID(git stash drop
这样做。)
请注意git commit --amend
实际上会进行 new 提交,将当前(HEAD)提交放在一边。也就是说,如果我们从:
...--F--G <-- branch (HEAD)
并运行git commit --amend
,Git将新提交 - 让我们调用此G2
- 其父级为F
,而不是正常的想法使用G
作为G2
的父级,然后将G2
的ID写入分支,给我们:
G
/
...--F--G2 <-- branch (HEAD)
只要旧的提交G
没有我们可以找到它的名称,Git就不会向我们展示它,并最终完全删除它,使它看起来好像我们以某种方式更改了提交{{1}进入G
。
要使现有的存储条目具有不同的提交注释,我们必须执行相同的操作:我们将现有的G2
提交复制到新提交,使用不同的提交邮件,但保留w
内容及其所有父哈希值。如果我们拨打替换w
,我们会:
w2
如果我们重新指向...--F--G_ <-- branch
|\`-.
i-w2 \
\ \
-----w <-- (the stash)
指向refs/stash
而不是w2
,并假装w
不再存在,我们就会得到我们想要的内容:
w
实际上我们可以把它写成一个脚本,从这些代码片段开始:
...--F--G <-- branch
|\
i-w2 <-- (the stash)
然后:
# get the parents of refs/stash as $1 and $2; $3 exists if there is a u commit
set -- $(git rev-parse refs/stash^@)
# convert these to "-p $1 -p $2 -p $3"
case $# in
2) parents="-p $1 -p $2";;
3) parents="-p $1 -p $2 -p $3";;
*) fatal "refs/stash does not appear to be a valid stash";;
esac
# find the stashed w commit's tree
tree=$(git rev-parse refs/stash^{tree}) || exit
# optional: for editing purposes, gather the current message
existing_message=$(git log --no-walk --pretty=format:%B refs/stash)
# obtain an updated message in some fashion
[snip]
并最终:
# create a new w commit, suitable for "git stash store"
new_w_commit=$(git commit-tree $parents "$new_message" $tree)
使用git stash drop --quiet
git stash store --quiet -m "$new_message" $new_w_commit
脚本本身用新存储替换git stash
。 (在中断的情况下,反转这两个操作的顺序可能更明智。使用stash@{0}
引用来确定如何执行此操作仍然是一个练习。这些都不会被远程测试。)