【问题标题】:What do the lines mean in Intellij Idea Git Log?Intellij Idea Git Log 中的这些行是什么意思?
【发布时间】:2021-05-28 07:28:15
【问题描述】:

Idea中按alt+9可以看到git日志窗口:

我看到那些点代表提交。这些线代表分支吗?如果是这样,如何确定每条线代表哪个分支?

我看看如果我悬停一行的某些部分,它的一部分被突出显示,突出显示的部分是什么意思?如果我单击它,它会变为虚线。刚刚发生了什么?

是否有文章或视频详细解释了 Idea git log 窗口或它使用的树状 git log 结构?我已经阅读了Idea's help page for git log window,但是关于这些台词的内容很少。

【问题讨论】:

    标签: git intellij-idea branch git-log


    【解决方案1】:

    从您的屏幕截图中:当您看到灰点时,您可以看到有一个线性提交序列,没有任何合并,当您将鼠标悬停在它上面时会突出显示。

    显然:单击悬停的行会隐藏此提交序列,并允许您专注于其他分支。
    这条线变成虚线可能表示“在这条线的两端之间有隐藏的提交”。
    单击虚线会使这些提交再次可见。

    我不知道 IntelliJ 如何选择可以折叠的序列;我的盲目猜测是:它可能会保留涉及合并的提交,以及引用(分支、标签或远程分支)指向的提交。

    【讨论】:

      【解决方案2】:

      您的部分问题是:

      这些线代表分支吗?如果是这样,如何确定每条线代表哪个分支?

      我在twocomments 中提到它们确实代表了......我们可能会调用分支的东西:

      • branch 这个词在 Git 中往往会失去所有意义,所以除了作为 name 的修饰符之外,何时使用这个词并不清楚。如果我们说master 是一个分支名称develop 是一个分支名称,等等,这些都很清楚。从技术上讲,masterrefs/heads/master 的简写,它是 refreference: 这是一种保存提交哈希 ID 的方式。1

      • 但我们还需要一种方法来引用某些提交组。我们也倾向于称其为一个分支

      • Git 提供远程跟踪名称,例如origin/master。我们经常将使用这样的名称找到的提交集合称为远程分支,Git 本身将这些东西称为远程跟踪分支名称,即使它们不是分支名称。2

      我发现branch这个词被过度使用到了经常变得毫无意义的地步。但这些线表示从提交到其他更早提交的链接

      我们通过从提交到提交来找到这些链接。当我们找到 starting 提交时,为了遵循这些提交到提交的链接,使用 分支名称,我们称其为 分支。但这与分支名称不是一回事,当我们看看它们是如何随着时间的推移而演变时,这里的问题就变得很清楚了。

      让我们从一个只有三个提交的存储库开始,全部在 mastermain 上,并使用大写字母而不是 Git 真正用于它们的又大又丑的哈希 ID 来绘制这三个提交:

      A <-B <-C   <--main
      

      namemain 保存了三个提交中最后的哈希 ID,即提交 C。提交C 本身持有早期提交B 的原始哈希ID,而提交B 持有仍然早期提交A 的原始哈希ID。我们说C指向BB指向A——当然main本身也指向C。

      提交A 是第一次提交。没有更早的提交!所以提交A 没有指向任何地方。这使它成为 root 提交,Git 可以在此处停止倒退。

      我们现在向我们的提交集合添加一个新的分支名称。这个新名字也指向提交C,像这样:

      A--B--C   <-- main, develop
      

      我们选择一个名称​​使用git checkout

      A--B--C   <-- main, develop (HEAD)
      

      我们现在通过名称develop 使用提交C。如果我们git checkout main,我们仍然使用C,只是通过不同的名称,但我们现在将坚持使用develop

      每个提交都包含每个文件的快照,并以特殊的、只读的、仅 Git 的、压缩的和 去重复 的形式永久冻结。所以C 中的大多数文件可能与B 中的文件相同,这意味着C 不会占用太多额外空间。如果 BC 共享一个 100 MB 的文件,则该文件只有一个副本

      但是这些文件不能被其他任何东西使用。所以git checkout 必须将它们复制出来 到一个可用的表单中。这就是您的工作树中的内容: 可用形式的副本。我们不会进一步讨论这个想法,但值得牢记并稍后重新审视。

      无论如何,现在让我们以通常的方式进行新的提交D。提交D 将像往常一样保存每个文件的(去重复的)快照,并将向后指向现有的提交C。当 Git 完成 D 的创建后,Git 将更新 当前分支名称,无论它是什么——基于 HEAD 的附件——指向 D,如下所示:

      A--B--C   <-- main
             \
              D   <-- develop (HEAD)
      

      提交A-B-C 现在在main 上,对吧?而D 仅在develop 上。嗯,last 部分是正确的——但提交 A-B-Cdevelop 上。

      您的查看器绘制的线,将D 向后连接到C 等等,不告诉您在哪个分支上,部分原因是分支不没关系。只有提交很重要。提交C 很重要,并且可以从两个名称中找到,因此它在两个分支上。将C 向后链接到B 的那一行现在代表两个 分支。

      我们可能会继续进行更多的提交:

      A--B--C   <-- main
             \
              D--E--F   <-- develop (HEAD)
      

      很容易将它们视为独立的,好像develop只有 D-E-F。在 Git 中情况并非如此:分支名称只对入门很重要。我们永远不知道什么时候该停止,除非我们遇到像A 这样的根提交。

      为了让 Git 更早停止,我们使用 main..develop 之类的表达式。这是develop ^main 的简写。这使用集合论:通过develop,我们找到所有提交,然后通过main,我们找到A-B-C 集合,然后我们减去排除的集合——^main 部分——整体。这给我们留下了D-E-F,这是我们可能想认为是“在分支develop”上的提交。但要到达那里,我们不得不说:develop 上的提交,减去 main 上的提交,因为A-B-C 位于两个分支上

      现在我们可以继续合并新的提交main。当我们这样做时,我们可以让 Git 进行 快进,这根本不是合并:

      git checkout main && git merge --ff-only develop
      

      结果:

      A--B--C--D--E--F   <-- develop, main (HEAD)
      

      现在所有六个提交都在两个分支上。现在只有一行,而不是两行:我们不必再分解绘图以使 main 指向 C

      或者,我们可以使用显式合并,或者先在main 上提交:

      git checkout main; (... make new commit ...); git merge develop
      

      导致:

      A--B--C------G--H   <-- main (HEAD)
             \       /
              D--E--F   <-- develop
      

      commit H 是一个合并提交。从H 出来有两个指向后的箭头:一个连接到之前的提交G(如果我们成功了,或者直接C,如果没有),另一个指向提交F。现在所有提交都在main上。合并提交 H onlymain 上(至少目前如此),但因为它向后指向两者......所有这些提交都可从提交H 访问,因此所有提交都“开启”main到目前为止有两行,但只有一个分支用于找到它们。

      当然还有那个名字develop,找到提交F,找到提交E,以此类推,一路回到A。提交F 因此在分支develop 上,就像以前一样。只是它现在在分支maintoo

      但是:现在我们可以完全删除名称develop,使用git branch -d develop。当我们这样做时,我们会得到这个:

      A--B--C------G--H   <-- main (HEAD)
             \       /
              D--E--F
      

      所有提交仍然存在。还有两条线。但现在只涉及一个分支名称

      这就是为什么我喜欢说分支名称无关紧要——当然不是为了找到一个提交。我们需要一些方法来找到提交H。只要我们有这个,我们也会找到所有早期的提交,因为它们是链接的,一个 - 或者对于合并提交 H,两个 - 一次,向后。

      您的可视化工具中的线条代表这些联系。链接是分支,或者不是分支,或者是任何你喜欢的,取决于你想如何查看它们。


      1我们最后在.git/config 中还有一个配置部分:

      [branch "master"]
          remote = origin
          merge = refs/heads/master
      

      例如,分支名称不仅仅是只是提交哈希ID。但是这两个条目大多是静态的:如果我们运行 git branch --set-upstream-toremotemerge 设置会发生变化,例如,要更改 masterupstream 设置。

      2运行git checkout origin/master,然后运行git status,我们看到这会产生分离的HEAD状态,而不是on branch origin/master状态。所以origin/master——其全拼是refs/remotes/origin/master——不是一个分支名称。由于 branch 这个词在 Git 中因过度使用而被严重殴打,所以我认为将其称为 远程跟踪分支名称 是个坏主意。 remote-tracking name 短语同样适用于识别这是什么类型的名称。

      【讨论】:

        【解决方案3】:

        是的,dots 是提交,lines 是分支。

        要知道它指的是哪个分支,只需查看右窗格,如下图所示:

        虚线仅表示您通过单击自己的提交选择的分支。

        【讨论】:

        • 从技术上讲,行不是分支,因为分支只是指向提交的指针。这些行代表提交的历史(之前发生了什么提交)(这相当于分支的历史)。
        • 一个提交至少存在一个分支,提交列表就是分支历史。
        • 分支历史:是的,但是这些行是不是分支,因为分支只是对提交的引用(实际上文件只包含提交哈希和换行符)。
        • 这说明了branch这个词的问题。 ? Git 分支是像master 这样的分支名称,还是通过连接线连接的一组提交,还是什么?这个问题的答案往往是“是”。这意味着在我们继续之前,我们需要弄清楚“什么”是什么。我们不妨说点是提交,行是 cronkins,master 是一个 cronkin,我们想创建一个新的 cronkin 等。它与 branch 一样有意义,即在我们弄清楚之前没有我们到底是什么意思。
        • 不过,这正确答案。点是提交,线条是......我们可能的意思。或者,也许这是错误的答案。我也会在这里尝试自己的答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-09
        相关资源
        最近更新 更多