如何在`git stash list`中列出一个存储的父提交?

7

当我在git中生成一个stash时,会有一个“父级”(即我stash我的更改之前的最后一次提交)。

当我使用git stash来存储我的更改时,会将指向该父级提交的ID添加到描述我的stash的消息中。调用git stash list可以显示:

stash@{0}: WIP on master: c09a3fc second commit
stash@{1}: WIP on master: 063b893 first commit
stash@{2}: WIP on master: 063b893 first commit

但是,当我运行git stash save "我的自定义信息"时,父提交的ID不会被添加到git stash list中:

stash@{0}: On master: My own message
stash@{1}: WIP on master: c09a3fc second commit
stash@{2}: WIP on master: 063b893 first commit
stash@{3}: WIP on master: 063b893 first commit

有没有办法在存储列表中显示父提交的ID?
我尝试了以下命令:git stash list --oneline --parents,但它只返回:
1b5dfb1 4efd3e0 refs/stash@{0}: On master: My own message
4efd3e0 1e9b384 refs/stash@{1}: WIP on master: c09a3fc second commit
1e9b384 51eb834 refs/stash@{2}: WIP on master: 063b893 first commit
51eb834 refs/stash@{3}: WIP on master: 063b893 first commit

但这里显示的ID是错误的。我期望的是(第一行是父提交的ID,在这个例子中,每两个提交的组的父提交是相同的):

c09a3fc 1b5dfb1 refs/stash@{0}: On master: My own message
c09a3fc 4efd3e0 refs/stash@{1}: WIP on master: c09a3fc second commit
063b893 1e9b384 refs/stash@{2}: WIP on master: 063b893 first commit
063b893 51eb834 refs/stash@{3}: WIP on master: 063b893 first commit

如果您想对单个存储进行操作,可以使用 git show stash@{0}^ 命令,因为 stash@{0} 是一个有效的引用名称。您可以编写一个小脚本来获取所需的输出 - 但这是读者的练习,所以这只是一条注释 :-) - Jan Fabry
@JanFabry 感谢您的评论。git show stash@{0}^是我在这里提出的问题的答案吗?https://stackoverflow.com/questions/62840077/how-to-recover-from-git-added-by-us-conflict-after-applying-stash-after-renami/62842712#comment111147132_62842712 - Ryan
此外,对于对这个话题感兴趣的人,我注意到这个问题非常相似:https://dev59.com/knHYa4cB1Zd3GeqPHRQ7 - Ryan
1个回答

6

如果您想在提供的消息中包含ID,则可以将ID作为消息的一部分提供。也就是说,不要使用以下格式:

$ git stash save "My own message"

你可能会运行:

$ git stash save "[$(git rev-parse --short HEAD)] My own message"

如果您想要使用存储在树中的父ID,您必须深入研究git stash的实现。具体细节请参见此答案,简而言之,工作树提交wrefs/stash或reflog条目,指向此w提交)的第一个父提交是在制作存储时处于HEAD状态的提交。

git stash list子命令只是直接将其他参数传递给git log,因此--oneline --parentsgit log的功能相同-除了git stash list以这种方式执行:

(您可以将其转换为别名- shell别名或调用shell的git别名)。

git log --format="%gd: %gs" -g --first-parent -m "$@" $ref_stash --

(其中“$ @”是您的附加参数)。不幸的是,--parents使用历史简化和父级重写(请参见git rev-list的文档),与-g一起,变成“用reflog walk的结果替换父系”,这完全破坏了原始的父系信息。
(顺便说一下,在此明确使用--first-parent的唯一原因是使--parents隐藏索引和可选的额外提交。由于--parents无论如何都会被reflog walk所覆盖,因此它似乎是没有意义的。不确定git开发人员是否可能希望reflog walks不会破坏父系信息,如果它没有破坏,您将看到所需的内容。因此,这可能是一个git错误,尽管在这里有很多猜测意图。)
您可以通过返回原始提交ID(w提交)并使用git rev-parse查找每个w提交的第一个父级来(有点)获得您想要的内容。
git log -g --format="%gd %H" refs/stash |
while read name hash; do
    printf "%s %s " $name $(git rev-parse --short $name^)
    git log -1 --format=%s $hash
done

(也许有缩短的方法,但以上方式相当直观。)

在macOS 10.12.6上,使用Git版本2.17.1时,我发现结果被打印成了一系列较小的屏幕。将| cat添加到上述命令中可以解决这个问题。 - cmicat
@cmicat:git log 根据您的配置设置使用或不使用分页器。设置 core.pager 来控制使用哪个分页器;使用 git --no-pager 来禁用一个命令的分页器;设置 pager.<cmd>(例如,pager.log)为 truefalse。由于 git log 用于许多其他事情,您可能不想在此更改其默认值。请注意,如果您使用 less 作为分页器,则可以在环境中设置 LESS 选项。如果没有,Git 将默认为您设置 FRX(这是 Git 构建时的选项)。 - torek
谢谢您的回答。您能否看一下我在这里提出的类似问题并进行澄清?https://dev59.com/yLzpa4cB1Zd3GeqPFSQW - Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接