git - 如何在 git log 中找到 gitlab 中指示的提交?
解决方案
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
,它没有父级。然后我们将B
其A
作为其父级,最后,我们将C
其B
作为其父级。
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 终于可以停止了。B
A
A
为了添加一个新的提交,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
即使分支名称本身移动,该名称仍会附加到分支名称。(对于那些好奇的人来说,这个的实际实现是在.git
named中有一个文件,它只HEAD
包含分支名称本身。所以HEAD
只有当你选择一个新的分支来使用时,内容才会改变。分支的内容name — 最新提交的哈希 IDmaster
和develop
— 存储在别处,在一个或多个不同的地方。)
请注意,顺便说一下,在这里的图中,提交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
. 它有两个父母,J
和L
。提交J
仅在发布时,它有一个父级I
。CommitL
在两个分支上,并且有一个 parent K
。两者I
和都K
返回到 commit H
,它在两个分支上,然后返回到G
,它在两个分支上,依此类推。
这是git log
进来的地方
如果你在git log
没有给它一些开始提交的情况下运行,Git会查看HEAD
你的当前提交。您当前的提交是您的分支名称指向的提交。您在评论中提到您在您的release
分支上并且它指向合并提交。所以你的照片可能看起来像我们刚刚画的一样。
该git log
命令将从提交开始M
并显示给您。然后它将所有的M
父母添加到它需要显示的提交列表中。它现在必须尝试同时向您J
展示L
两者。它不能,所以它选择这两个中的一个来显示。然后它将显示的任何一个的父级添加到要显示的内容列表中。
如果它只是显示J
,git log
现在有两个提交同时显示给你,即L
和I
。它不能同时显示两者,所以它选择一个。然后它将那个人的父母添加到它的列表中,依此类推。
默认情况下,该git log
命令将混合来自合并两侧的提交。特别是,它会根据时间戳一次显示一个,以便您首先看到较新的。IfJ
比L
您J
之前看到的要新L
,但 ifL
比J
您L
首先看到的要新。I
和(与K
两者相比)也是如此。但是确实尊重图形的形状,因为无论它做什么,它都不会显示,直到它完成显示and 。L
J
git log
H
I-J
K-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/develop
or的名称origin/master
,您的 Git 使用它来记住您的 Git 在其他 Git 中看到的分支名称。
运行git log
不会显示 commit P
。没有显示P
它不会回到O
任何一个。Git 字面上不能从L
to 转到N
. 它只能从N
到L
,后退。您需要选择一个起始提交哈希,该哈希从您关心的提交处或之后开始,以查看您关心的提交。
请注意,N-O-P
此处的提交不是 "on" release
。我们使用“on”这个词来表示“可以从提示到达的提交”。的提示release
是提交M
,并且N
无法通过从M
.
请注意,M
从任何一个向后退都无法达到提交N
!两个提交可以有一个共同的祖先,而它们本身没有父/子或祖父母/孙子关系。他们有共同祖先的事实可能只会使他们成为兄弟姐妹或堂兄弟。
推荐阅读
- powershell - 从已经具有一系列值的数组中填充属性值 - PowerShell
- android - 当键盘在三星平板电脑中启动时,滚动视图不会滚动到结束
- r - 通过 R 中的 SCP 发送文件
- javascript - scrollview insde flatlist 不滚动
- c# - 最初对 acctName 上的销售订单客户查找进行排序
- variables - GNU Make,来自多个先决条件行的 `$<` 的值
- git - 具有不同目录结构的 Git 分支
- php - 为什么我对 url 的第二次调用不起作用(Laravel,Guzzle)?
- reactjs - 反应本机和箭头功能
- c# - 从 SQL 数据库读取 BLOB 对象时文件损坏