`git diff HEAD^` 的反义词是什么?

28

在git中,我可以使用HEAD^HEAD~1来指定前一个版本。那么倒过来呢?假设我在版本X上,并且执行了git checkout X^,我如何回到之前的版本?

是否类似于git checkout X+


4
你是想回到HEAD^的相反版本,还是只是想要“返回”的方式?(你可以使用HEAD@{1}来回到以前的HEAD。) - nschum
4个回答

36
您无法准确地这样做。 Git中的历史记录是有向无环图 - 每个提交包含对其父项的引用,但父项没有对其子项的引用。
当您考虑从多个分支创建的提交时,问题就变得明显了。您指的是哪个“下一个提交”?通过父项,您可以编号(正常合并提交具有第一和第二父项),但是如何处理子项?即使您知道要使用哪个分支(例如,您已检出master〜4,现在您想查看master〜3),它也不是明确定义的 - 您可能处于以下情况:
- X (HEAD) - o - o - o - Y (master)
   \                    /
    o - o - o ----------

话虽如此,在简单的情况下,您可以像这样做:

git checkout $(git rev-list HEAD..master | tail -n 1)

显然,这对于线性历史记录可以正常工作。对于合并......rev-list从现在向过去遍历历史记录,向后跟随它。我相信它首先遵循第一个父节点,因此最后打印的东西将是在跟随所有上一个父节点找到的HEAD之后提交的。

编辑:这假设您知道要向前移动的分支。如果不知道......嗯,您几乎无法查看所有引用以获取具有当前HEAD作为父项的提交-可能会搜索git rev-parse的输出:

git rev-list --all --children | grep ^$(git rev-parse HEAD)

然后从该行中提取另一个SHA1(使用awk或其他工具)。如果有多个结果,则需要手动检查或进行任意选择...


从技术上讲,同样的问题也存在于另一种情况下,即如果head在点Y处,HEAD^将沿着哪条路径返回?两个分支可能都是主分支...我认为另一个答案可能更准确,即每个提交存储父提交,而HEAD^使用它。 - SEoF

3

我认为这是不可能的,因为Git提交只存储它的父提交,而不是它的子提交。

想象一下,如果一个提交要存储它的子提交,那么如果你从这个提交创建多个分支,那么多个提交都将以此提交为父提交?这是模糊和错误的。

就我所知的数据结构来说: Git将历史记录存储为单向链表,而您的操作需要一个双向链表。


这情况比那还要糟糕一些——请看我关于即使父母知道孩子情况仍存在歧义的回答。 - Cascabel

2
据我所知,目前没有一种符号方式来引用提交的子级。
目前最好的方法是使用git rev-list命令的--children选项。在这里,我请求将最近的四个提交进行漂亮的打印,并提供它们的子级信息。请注意,在每个条目的“提交”行(除了最新的条目)中,有一个额外的提交编号,指定该节点的子级。您可以手动获取或通过一些shell脚本来获取到子级。
$ git rev-list --children --pretty HEAD~3...

commit 20dba296ad1d48ec90f9319e2c13b245e849f698
Author: Somebody <____@____.net>
Date:   Thu May 6 19:10:38 2010 -0400

    Support for complex trig/pow.

commit 9d42b5bac1721a847a39c25672e577c7101c8ff0 20dba296ad1d48ec90f9319e2c13b245e849f698
Author: Somebody <____@____.net>
Date:   Wed May 5 21:55:07 2010 -0400

    Fix doc formatting warning.

commit 72bed3baa9df71cb224dfa8388b5969d50f5567c 9d42b5bac1721a847a39c25672e577c7101c8ff0
Merge: b8244cb61491c9cdb83d36e57f8eb49773e44f6b 899c3dd3f9f419f200b84ca0abe59d7ac3d5bb53
Author: Somebody <____@____.net>
Date:   Wed May 5 21:54:59 2010 -0400

    Merge branch 'master' 

commit 899c3dd3f9f419f200b84ca0abe59d7ac3d5bb53 72bed3baa9df71cb224dfa8388b5969d50f5567c
Author: Somebody <____@____.net>
Date:   Wed May 5 21:19:11 2010 -0400

    Fix link

0
作为务实的答案,只需使用git checkout -返回到上一个位置,90%的情况下它将是您想要的位置。
这不是在查找子节点并以相反的顺序遍历树之类的操作。该语法基于流行的cd -,类似地,git checkout -并不像cd ..那样“返回到上一级目录”。它只是将您带回到之前已知的最后一个位置。

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