我知道Git中的历史存储在一个名为DAG的数据结构中。我听说过DFS并且知道它有点相关。
我很好奇,git log --graph
或hg graphlog
等程序如何绘制历史记录?我一直认为以一种很好的方式画出车道和一切都很复杂。
有人可以编写一些演示它的伪代码吗?
注意:我试着查看Git或hg的代码,但很难跟进并大致了解发生了什么。
答案 0 :(得分:6)
首先,获取提交列表(与git rev-list
一样),以及每个提交的父项。 “列保留列表”保留在内存中。
对于每次提交,然后:
示例显示了aufs2-util上的git-forest
输出,并且额外提交了多个分支。
通过前瞻,可以预测合并点下方的距离,并在两列之间挤压木材,以获得更美观的结果。
答案 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
”的工作方式。
git config --global core.commitGraph true
git config --global gc.writeCommitGraph true
cd /path/to/repo
git commit-graph write
请参阅commit 7547b95,commit 3d5df01,commit 049d51a,commit 177722b,commit 4f2542b,commit 1b70dfd,commit 2a2e32b(2018年4月10日) ,commit f237c8b,commit 08fd81c,commit 4ce58ee,commit ae30d7b,commit b84f767,commit cfe8321,commit f2af9f5(2018年4月2日){ {3}}。
(由Derrick Stolee (derrickstolee
)合并于Junio C Hamano -- gitster
--,2018年5月8日)
您现在拥有命令commit b10edb2:编写并验证Git提交图形文件。
根据packfiles中的提交编写提交图文件 包括现有提交图文件中的所有提交。
Git遍历提交图表有很多原因,包括:
- 列出并过滤提交历史记录。
- 计算合并基础。
醇>随着提交计数的增长,这些操作可能会变慢。合并 基本计算显示在许多面向用户的命令中,例如“merge-base” 或“状态”,可能需要几分钟来计算,具体取决于历史形状。
这里有两个主要成本:
- 解压缩和解析提交。
- 遍历整个图表以满足拓扑顺序约束。
醇>提交图文件是一种加速的补充数据结构 提交图表。 如果用户降级或禁用“
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 33286dc,commit 1472978,commit 7adf526,commit 04bc8d1,commit d7c1ec3,commit f9b8908 ,commit 819807b,commit e2838d8,commit 3afc679(2018年5月1日)和commit 3258c66,commit 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
目录中的提交图文件 在某些情况下,此目录可能不存在,因此我们检查它是否存在。现有代码在获取锁时执行以下操作:
- 尝试获取锁定。
- 如果失败,请尝试创建
.git/object/info
目录。- 尝试获取锁定,必要时失败。
醇>问题是如果锁存文件存在,则mkdir失败,给出 一个对用户没有帮助的错误:
"fatal: cannot mkdir .git/objects/info: File exists"
虽然从技术上来说这是对lockfile的尊重,但它对用户没有帮助。
相反,请执行以下操作:
- 检查是否存在
.git/objects/info
;必要时创建。- 尝试获取锁定,必要时失败。
醇>新输出如下:
fatal: Unable to create '<dir>/.git/objects/info/commit-graph.lock': File exists.
另一个git进程似乎正在此存储库中运行,例如 由'git commit'打开的编辑器。请确保所有流程 终止然后再试一次。如果它仍然失败,那就是一个git进程 可能早先在此存储库中崩溃: 手动删除文件以继续。
注意:当内核对象时,提交图工具不起作用 从未知类型提升为提交(例如,提交是 通过引用它的标签访问,参与其中 用Git 2.21(2019年2月)纠正
commit a856e7d见commit 4468d44(2019年1月27日)
(SZEDER Gábor (szeder
)合并于Junio C Hamano -- gitster
--,2019年2月5日)