首页 > 解决方案 > 如何在 git log 中找到 gitlab 中指示的提交?

问题描述

请看 gitlab 中的环境镜像在我们的案例中有一个提交版本 8d6995e4。我在做 git log | grep 并找不到此提交版本。这个字符串表示什么? 在此处输入图像描述

标签: gitgitlab

解决方案


TL;博士

当你运行时,git log你告诉它从哪个提交开始。如果您不告诉它,它将假定当前分支的当前提交。它找到从该起点可以找到的其余提交。您的存储库中有提交8d6995e4,但它不在您当前的分支上。

您可以使用git log --all告诉它从所有记录的起点(分支名称、标签名称、远程跟踪名称等)开始,并且您可能想要Get Help From A Dog,或者按照OznOg 的建议,使用视觉观察者。另请参阅漂亮的 git 分支图

要了解这里发生了什么,您需要了解提交——这是 Git 存在的理由——以及 Git 如何找到它们,通常从分支名称开始。这涉及到图表中可达性的概念,在Think Like (a) Git中以更长、更彻底的方式解释了这一点。

提交

每个提交都有自己唯一的哈希 ID。那就是你在这里看到的那个又大又丑的字符串,8d6995e4(尽管实际上它要长得多——40 个字符显然是随机的垃圾,实际上根本不是随机的)。该哈希 ID 是提交的“真实名称”:它是 Git 在“所有提交过”的数据库中找到提交的方式(人们所做的主要事情是添加更多提交)。

每个提交还拥有一个提交哈希 ID。也就是说,某个父提交的子级会记住父级的哈希。父母不记得他们的孩子,因为一旦做出承诺,它里面的任何东西都不会改变。 这种提交的冻结性对许多其他 Git 命令无关紧要,git log但对许多其他 Git 命令却很重要。

上面的内容有点夸张,因为至少有一个提交——有人在一个新的空存储库中进行的第一个提交——没有父级。此提交的父级是提交之前的提交。第一次提交之前没有提交。而且,合并提交有多个父级,这就是它们合并提交的原因。

这一切意味着提交形成了一个向后看的链。正是这个反向链git log使用。这是一个只有三个提交的存储库的简单绘图,其中我只使用一个大写字母,而不是丑陋的 40 个字符的哈希 ID。显然我们会很快用完——存储库将在 26 次提交时满——所以这不是 Git 的做法,但它确实很好地说明了这个问题。我们的第一个提交是A,它没有父级。然后我们将BA作为其父级,最后,我们将CB作为其父级。

A <-B <-C

因为提交中的任何内容都不会改变,所以我们可以将从子节点到父节点的反向连接绘制成双向的线,只要我们记住Git必须反向。这在 StackOverflow 帖子中对我来说更方便,因为我有时还需要做对角线:

A--B--C
       \
        D

而且我没有适合这里每个人的方便的文本箭头。

分支名称指向提交,但也会移动

现在,为了git log工作,你必须给它一个开始提交——一个哈希 ID。事实上,要让 Git 中的很多东西起作用,你必须给它们一个哈希 ID。但真正的哈希 ID 又大又丑 ( 8d6995e4) 并且显然是随机的。它们绝对不是一个合理的顺序,人类没有办法记住它们。所以我们要做的是选择一个分支名称,例如master. 我们让 Git 将最后一次提交的哈希 ID 推送到分支名称中,这意味着我们的绘图现在看起来像这样:

A--B--C   <-- master

名称让 Git 可以找到最后一次提交,在本例中为C. 从那里,向后git log走到,然后回到,然后由于没有父级,Git 终于可以停止了。BAA

为了添加一个的提交,Git 会打包你提交的任何东西——一个新的快照——并添加元数据,比如你的姓名和电子邮件地址、当前时间和你的日志消息。Git 会自动将当前提交的哈希 ID 添加到元数据中。Git 将所有这些写入对象数据库,并且写入它的行为为这个新提交分配其唯一的哈希 ID。当然,那是另一个大而丑陋的数字,但我们将使用字母D

A--B--C   <-- master
       \
        D

记住这D 我们最后一次提交,Git 现在更新了我们的名字master

A--B--C
       \
        D   <-- master

所以现在git log将开始D,然后显示C,然后B,然后A

使用您的 HEAD 更改您看到和更新的内容

重要的是提交。分支名称可以帮助我们找到它们。但是当我们有多个分支名称时会发生什么?在我们进行了一些提交之后,让我们看一个稍微复杂一点的图表:

...--C--D   <-- master
         \
          E--F   <-- develop

我们在上面说过,当我们进行新的提交时,Git 会移动分支名称。但是 Git 是如何知道要移动哪个分支名称的呢?如果我们有:

...--C--D   <-- develop, master

——我们可能在某个时候做过——Git 怎么知道,当我们提交E时,它应该移动,而不是开发master

答案是我们git checkout只将特殊名称附加HEAD到一个分支上。如果我们选择develop,我们得到:

...--C--D   <-- develop (HEAD), master

然后当我们添加 commit 时E,Git 移动develop

...--C--D   <-- master
         \
          E   <-- develop (HEAD)

HEAD即使分支名称本身移动,该名称仍会附加到分支名称。(对于那些好奇的人来说,这个的实际实现是在.gitnamed中有一个文件,它只HEAD包含分支名称本身。所以HEAD只有当你选择一个新的分支来使用时,内容才会改变。分支的内容name — 最新提交的哈希 IDmasterdevelop— 存储在别处,在一个或多个不同的地方。)

请注意,顺便说一下,在这里的图中,提交A-B-C-D两个分支上。提交E-F仅在develop. 但是由于我们可以移动分支名称,我们可以通过移动master指向来改变它F。这将使所有六个提交都在两个分支上。我们不必更改提交来执行此操作,这是必要的,因为我们不能。:-)

图表可以变得更加复杂。这里没有显示一个非常复杂的(就像您可能实际拥有的那样),而是一个更简单的显示当我们提交合并时会发生什么。这是之前的图片:

          I--J   <-- release (HEAD)
         /
...--G--H
         \
          K--L   <-- develop

之后的一个:

          I--J
         /    \
...--G--H      M   <-- release (HEAD)
         \    /
          K--L   <-- develop

新的合并提交M仅在release. 它有两个父母,JL。提交J仅在发布时,它有一个父级I。CommitL两个分支上,并且有一个 parent K。两者I和都K返回到 commit H,它在两个分支上,然后返回到G,它在两个分支上,依此类推。

这是git log进来的地方

如果你在git log没有给它一些开始提交的情况下运行,Git会查看HEAD你的当前提交。您当前的提交是您的分支名称指向的提交。您在评论中提到您在您的release分支上并且它指向合并提交。所以你的照片可能看起来像我们刚刚画的一样。

git log命令将从提交开始M并显示给您。然后它将所有M父母添加到它需要显示的提交列表中。它现在必须尝试同时向您J展示L 两者。它不能,所以它选择这两个中的一个来显示。然后它将显示的任何一个的父级添加到要显示的内容列表中。

如果它只是显示Jgit log现在有两个提交同时显示给你,即LI。它不能同时显示两者,所以它选择一个。然后它将那个人的父母添加到它的列表中,依此类推。

默认情况下,该git log命令将混合来自合并两侧的提交。特别是,它会根据时间戳一次显示一个,以便您首先看到较新的。IfJLJ之前看到的要新L,但 ifLJL首先看到的要新。I和(与K两者相比)也是如此。但是确实尊重图形的形状,因为无论它做什么,它都不会显示,直到它完成显示and 。LJgit log HI-JK-L

最终,它将能够显示H,并且当它显示时,其他要显示的提交列表将为空。它将显示H,将H的父级添加G到要显示的列表(现在只有一个条目),然后显示G并添加G的父级,依此类推。

git log 不会M显示从开始和向后工作无法实现的提交!

          I--J
         /    \
...--G--H      M   <-- release (HEAD)
         \    /
          K--L   <-- develop
              \
               N--O--P   <-- another-name

假设有一些其他名称记住了哈希 ID P。这可能不是一个分支名称:它可能是一个类似于origin/developor的名称origin/master,您的 Git 使用它来记住您的 Git 在其他 Git 中看到的分支名称。

运行git log 不会显示 commit P。没有显示P它不会回到O任何一个。Git 字面上不能从Lto 转到N. 它只能从NL后退。您需要选择一个起始提交哈希,该哈希从您关心的提交处或之后开始,以查看您关心的提交。

请注意,N-O-P此处的提交不是 "on" release。我们使用“on”这个词来表示“可以从提示到达的提交”。的提示release是提交M,并且N无法通过从M.

请注意,M从任何一个向后退都无法达到提交N!两个提交可以有一个共同的祖先,而它们本身没有父/子或祖父母/孙子关系。他们有共同祖先的事实可能只会使他们成为兄弟姐妹或堂兄弟。


推荐阅读