git存储元素存储在哪里?数据结构真的是堆栈吗?

时间:2017-03-17 17:03:08

标签: git data-structures language-agnostic

为了更好地理解git stash,我想知道:git存储的元素存储在哪里和哪个数据结构中?在一堆?在一个有序的集合?

详细信息:

每个文档,文章和书籍(Git Internals除外)都表示git stash是堆栈

最近,我发现你可以从藏匿处以任意顺序检索和删除元素 - 这是一个有用的功能。由于此功能和A Hacker's Guide to Git,在我看来,存储包含一个按时间顺序排列的参考。但是,在.git/refs/stash中,只有最新的存储元素以合并提交的形式存储(其中还包含创建存储元素的日期)。

是否有另一个(top-secret pre-index stash-cache;)数据结构包含所有存储元素?或者git stash(list | pop | apply)从常规对象库中检索元素吗?怎么样?

那么隐藏元素形成了什么数据结构?合并日期隐含给出的元素的时间顺序是否提交?如果元素实际上存储在堆栈中,git如何以任意顺序检索和删除元素?

1 个答案:

答案 0 :(得分:2)

作为ElpieKay wrote in a comment当前藏匿的所有内容都存储在引用 refs/stash的reflog中。请参阅the gitglossary中“ref”和“reflog”的定义。请注意,masterdevelop等分支名称是一种引用,分别是全名refs/heads/masterrefs/heads/develop的缩写。标签名称是另一种参考;标记v2.2实际上是引用refs/tags/v2.2

大多数引用都以refs/为前缀。事实上,各种HEAD - HEAD本身,MERGE_HEADCHERRY_PICK_HEADORIG_HEAD等等 - 是唯一的例外情况,而且大多数那些< / em>不拥有 reflogs。 HEAD是唯一能做到的人。

通常,reflog条目只是线性编号:HEAD@{1}master@{1}是“HEADmaster在最近更新之前指向的提交”,{ {1}}是两步之前的提交,依此类推。这在gitrevisions中有所描述。为方便起见,可以使用master@{2}引用当前值:@{0}并且master@{0}始终解析为相同的哈希ID。如果master引用的使用方式与其他引用相同,则它将作为队列而不是堆栈工作 - 但它不是使用。相反,refs/stash代码显式删除早期条目。

由于编号始终是连续的,因此删除条目会导致所有更高数字下降一。例如,如果您手动删除git stash,那么以前的master@{5}现在是master@{6},过去的master@{5}现在是master@{7},所以上。

当然,添加一个新条目会推动一切。因此,当您创建新的存储时,以前为master@{6}又名stash的存储现在为stash@{0}。曾经是stash@{1}的人现在是stash@{1},依此类推。对于其他reflog,如stash@{2},没有人称之为“推”,这只是普通的队列。

删除 master又称stash@{0}后,所有较高的条目 - stashstash@{1}等等 - 下拉一个,所以现在stash@{2}已“弹出”,之前的stash只是stash@{1}。当然,您也可以stash删除该特定条目,保持0到3并重新编号为5-and-up。请注意,任何特定存储的git stash drop stash@{4}仅表示“应用,如果这似乎成功,则删除”。

请注意,并非完全偶然的是,每个reflog条目都附有时间戳。您可以编写git stash popmaster@{yesterday},Git会根据时间戳找到相应reflog条目的哈希ID。 1 因为stash标识符只是reflog条目,所以相同的语法在那里工作(我从来没有真正发现这一切在任何地方都有用,也许是因为我在工作时没有时间感,也不记得一周中哪一天现在,更不用说我早些时候做了什么。:-))要使用这些时间戳,大多数 reflogs 过期:默认情况下,旧的reflog条目将在90天后消失,或者仅在30天后消失它所指定的对象不能从同一参考的当前值到达 2 但是,默认情况下,master@{3.hours.ago}本身免于此过期。所有这些都是可配置的:请参阅the git config documentation中的所有refs/stash设置。

1 如果您在一天内多次更新参考但每小时不超过一次,gc.reflogExpire表示@{yesterday}。如果您每小时更新一次,请再乘以60:@{24.hours.ago}。如果您每分钟更新一次,请再次乘以60:@{1440.minutes.ago}。决议没有比那更好。

2 这就是Git保留30天的方式,但最终还是清除了@{86400.seconds.ago}遗弃的旧提交。 Reachability 是由存储库中的标记,提交和树对象形成的有向非循环图或DAG提供的关键概念。 (Blob是 DAG中,但没有任何部分扩展它,因为它们总是叶子节点。因此blob本身可以到达或无法访问,但它永远不会影响任何其他<的可达性/ em> object。)