如何修改 git stash 中的消息?

Luc*_*rts 5 git

假设我太快地将存储放入 git 中并且没有提供信息丰富的存储消息。我想修改存储中的消息,但无法从 git 文档中找到执行此操作的方法。我可以使存储库达到干净状态,然后弹出存储并重新应用 w/git stash save“我的保存消息”,但想知道是否有人有解决方案来修改消息。

tor*_*rek 6

这在技术上是不可能的,但通过欺骗很容易达到预期的目标。Git 只是没有任何内置机制来完成这个骗局,尽管它git commit有一个--amend选项可以做到这一点。(也没有干净的方法来劫持git commit --amend这个。)

\n\n

最后,你必须按照你的建议去做。如果您愿意,您可以将其隐藏在脚本中,但对于一次性情况,这比手动完成更多工作。

\n\n

技术细节,如果您想构建脚本

\n\n

在 Git 命令行命令和选项等的背后,Git 存储条目实际上一次提交。更准确地说,至少有两次提交,有时甚至是三次。 文档git stash在标记为“讨论”的部分中描述了这一点(相当轻松和粗心),git stash提交的特殊之处在于它们不在分支\xe2\x80\x94上,而且w集群中的(工作树)提交,即引用所refs/stash定位的提交,具有合并提交的形式,因此它可以列出多个父提交 ID。我更喜欢将它们绘制为:

\n\n
...--F--G   <-- branch\n        |\\\n        i-w   <-- (the stash)\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者:

\n\n
...--F--G   <-- branch\n        |\\\n        i-w   <-- (the stash)\n         /\n        u\n
Run Code Online (Sandbox Code Playgroud)\n\n

这与 Git 文档绘图有点不同,但显示了我所说的存储包(带有u保存未跟踪文件的可选提交)如何与您进行存储时当前的提交悬挂在一起。(如果您还没有将您的内容移到HEAD其他地方,则该提交仍然是是当前提交。)这里的大写字母代表实际的提交哈希值,它又大又难看,并且无法记住。

\n\n

与所有提交一样,特殊的存储提交是只读的\xe2\x80\x94,它们永远无法更改,只能忘记它们的哈希 ID(这就是原因git stash drop)。

\n\n

请注意,git commit --amend实际上会进行新的提交,将当前的(HEAD)提交推到一边,让开。也就是说,如果我们从以下开始:

\n\n
...--F--G   <-- branch (HEAD)\n
Run Code Online (Sandbox Code Playgroud)\n\n

并运行git commit --amend,Git 进行一个新的提交\xe2\x80\x94let\'s 调用此G2\xe2\x80\x94,其父级是F而不是使用GasG2的父级的正常想法,然后将G2\'s ID 写入分支,给我们:

\n\n
       G\n      /\n...--F--G2  <-- branch (HEAD)\n
Run Code Online (Sandbox Code Playgroud)\n\n

只要旧的提交G没有我们可以找到的名称,Git 就永远不会向我们显示它,并最终完全删除它,使我们看起来好像我们以某种方式将提交更改GG2.

\n\n

要使现有的存储条目具有不同的提交注释,我们必须做同样的事情:我们将现有的w提交复制到新的提交,并使用不同的提交消息,但保留w内容及其所有内容父哈希值。如果我们打电话给替代者w2我们会得到:

\n\n
...--F--G_  <-- branch\n        |\\`-.\n        i-w2 \\\n         \\    \\\n          -----w   <-- (the stash)\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我们然后重新指向refs/stash指向w2而不是w,并假装w不再存在,我们就会得到我们想要的:

\n\n
...--F--G   <-- branch\n        |\\\n        i-w2  <-- (the stash)\n
Run Code Online (Sandbox Code Playgroud)\n\n

事实上,我们可以将其编写为脚本,从以下代码片段开始:

\n\n
# get the parents of refs/stash as $1 and $2; $3 exists if there is a u commit\nset -- $(git rev-parse refs/stash^@)\n# convert these to "-p $1 -p $2 -p $3"\ncase $# in\n2) parents="-p $1 -p $2";;\n3) parents="-p $1 -p $2 -p $3";;\n*) fatal "refs/stash does not appear to be a valid stash";;\nesac\n# find the stashed w commit\'s tree\ntree=$(git rev-parse refs/stash^{tree}) || exit\n# optional: for editing purposes, gather the current message\nexisting_message=$(git log --no-walk --pretty=format:%B refs/stash)\n\n# obtain an updated message in some fashion\n[snip]\n
Run Code Online (Sandbox Code Playgroud)\n\n

进而:

\n\n
# create a new w commit, suitable for "git stash store"\nnew_w_commit=$(git commit-tree $parents "$new_message" $tree)\n
Run Code Online (Sandbox Code Playgroud)\n\n

最终:

\n\n
git stash drop --quiet\ngit stash store --quiet -m "$new_message" $new_w_commit\n
Run Code Online (Sandbox Code Playgroud)\n\n

它使用git stash脚本本身来替换stash@{0}新的存储。(在发生中断的情况下,颠倒这两个操作的顺序可能更明智。弄清楚如何使用stash@{n}将作为练习。这些都没有经过远程测试。)

\n