'git log --graph'或'hg graphlog'如何工作?

时间:2011-01-19 19:26:23

标签: algorithm git mercurial

我知道Git中的历史存储在一个名为DAG的数据结构中。我听说过DFS并且知道它有点相关。

我很好奇,git log --graphhg graphlog等程序如何绘制历史记录?我一直认为以一种很好的方式画出车道和一切都很复杂。

有人可以编写一些演示它的伪代码吗?

注意:我试着查看Git或hg的代码,但很难跟进并大致了解发生了什么。

4 个答案:

答案 0 :(得分:6)

首先,获取提交列表(与git rev-list一样),以及每个提交的父项。 “列保留列表”保留在内存中。

对于每次提交,然后:

  • 如果提交没有为其保留列,请将其分配给空闲列。这就是分支机构的起点。
  • 根据列预留列表打印树形图形,然后打印提交消息
  • 使用当前提交的第一个父级更新当前列/提交的预留列表条目,以便将父级打印在同一列中。
  • 其他家长获得一个新的免费专栏。
  • 如果这是一个合并,下一行将尝试将第二个父链接到一个预期提交的列(这使得循环和“≡bridge”)

示例显示了aufs2-util上的git-forest输出,并且额外提交了多个分支。

Example

通过前瞻,可以预测合并点下方的距离,并在两列之间挤压木材,以获得更美观的结果。

答案 1 :(得分:4)

  

我试着查看Git或hg的代码,但很难跟踪并大致了解发生了什么。

对于hg,您是否尝试按照hg本身或graphlog中的代码进行操作?

因为graphlog的代码很短。你可以在hgext/graphlog.py找到它,真正重要的部分是前200行,其余的是扩展的引导并找到选择的修订图。代码生成函数是ascii,其最后一个参数是调用asciiedge的结果(调用本身在generate的最后一行执行,函数提供给{ {1}} generate

答案 2 :(得分:3)

与一般的图表显示相比,这个特殊问题并不那么难。因为您希望按照提交的顺序保留节点,所以问题变得更加简单。

另请注意,显示模型是基于网格的,行是提交,列是过去/未来的边缘。

虽然我没有阅读git源代码,但您可能只是从最新的开始执行提交列表,并保留过去的开放边缘列表。在边缘之后自然会导致分割/合并列,最终会出现一种树git / hg显示。

合并边缘时,您希望避免穿过其他边缘,因此您必须提前尝试订购列。这实际上是唯一可能不是直截了当的部分。例如,可以执行双遍算法,在第一遍中构成边的列顺序,并在第二遍中进行绘制。

答案 3 :(得分:0)

注意:Git 2.18(2018年第二季度)现在可以预先计算并存储祖先遍历所需的信息,以便优化图形行走。

提交图表的概念确实会改变“git log --graph”的工作方式。

作为mentioned here

git config --global core.commitGraph true
git config --global gc.writeCommitGraph true
cd /path/to/repo
git commit-graph write

请参阅commit 7547b95commit 3d5df01commit 049d51acommit 177722bcommit 4f2542bcommit 1b70dfdcommit 2a2e32b(2018年4月10日) ,commit f237c8bcommit 08fd81ccommit 4ce58eecommit ae30d7bcommit b84f767commit cfe8321commit f2af9f5(2018年4月2日){ {3}}。
(由Derrick Stolee (derrickstolee)合并于Junio C Hamano -- gitster --,2018年5月8日)

您现在拥有命令commit b10edb2:编写并验证Git提交图形文件。

  

根据packfiles中的提交编写提交图文件   包括现有提交图文件中的所有提交。

git commit-graph州:

  

Git遍历提交图表有很多原因,包括:

     
      
  1. 列出并过滤提交历史记录。
  2.   
  3. 计算合并基础。
  4.         

    随着提交计数的增长,这些操作可能会变慢。合并   基本计算显示在许多面向用户的命令中,例如“merge-base”   或“状态”,可能需要几分钟来计算,具体取决于历史形状。

         

    这里有两个主要成本:

         
        
    1. 解压缩和解析提交。
    2.   
    3. 遍历整个图表以满足拓扑顺序约束。
    4.         

      提交图文件是一种加速的补充数据结构   提交图表。   如果用户降级或禁用“core.commitGraph”配置设置,则现有ODB就足够了。

           

      该文件存储为“commit-graph”,可以存储在.git/objects/info目录中,也可以存储在备用文件的info目录中。

           

      提交图文件存储提交图结构以及一些提交图结构   额外的元数据,以加快图形行走。
        通过按字典顺序列出提交OID,我们可以为每个提交标识一个整数位置,并使用这些整数位置引用提交的父级。
        我们使用二进制搜索来查找初始提交,然后使用整数位置   用于在步行期间快速查找。

您可以看到design document

git log --oneline $BRANCH
git log --topo-order $BRANCH
git log --graph $COMPARE..$BRANCH
git branch -vv
git merge-base -a $BRANCH $COMPARE

这会改善test use cases

Git 2.19(Q8 2018)将负责锁定文件:

请参阅git log performance(2018年5月10日),commit 33286dccommit 1472978commit 7adf526commit 04bc8d1commit d7c1ec3commit f9b8908commit 819807bcommit e2838d8commit 3afc679(2018年5月1日)和commit 3258c66commit 83073cc(2018年4月25日)commit 8fb572a
帮助:Derrick Stolee (derrickstolee)
(由Jeff King (peff)合并于Junio C Hamano -- gitster --,2018年6月25日)

  

commit-graph:修复.lock文件存在时的UX问题

     

我们使用lockfile API来避免多个Git进程写入   .git/objects/info目录中的提交图文件   在某些情况下,此目录可能不存在,因此我们检查它是否存在。

     

现有代码在获取锁时执行以下操作:

     
      
  1. 尝试获取锁定。
  2.   
  3. 如果失败,请尝试创建.git/object/info目录。
  4.   
  5. 尝试获取锁定,必要时失败。
  6.         

    问题是如果锁存文件存在,则mkdir失败,给出   一个对用户没有帮助的错误:

    "fatal: cannot mkdir .git/objects/info: File exists"
    
         

    虽然从技术上来说这是对lockfile的尊重,但它对用户没有帮助。

         

    相反,请执行以下操作:

         
        
    1. 检查是否存在.git/objects/info;必要时创建。
    2.   
    3. 尝试获取锁定,必要时失败。
    4.         

      新输出如下:

      fatal: Unable to create
      '<dir>/.git/objects/info/commit-graph.lock': File exists.
      
           

      另一个git进程似乎正在此存储库中运行,例如       由'git commit'打开的编辑器。请确保所有流程       终止然后再试一次。如果它仍然失败,那就是一个git进程       可能早先在此存储库中崩溃:       手动删除文件以继续。

注意:当内核对象时,提交图工具不起作用 从未知类型提升为提交(例如,提交是 通过引用它的标签访问,参与其中 用Git 2.21(2019年2月)纠正

commit a856e7dcommit 4468d44(2019年1月27日) SZEDER Gábor (szeder)合并于Junio C Hamano -- gitster --,2019年2月5日)