为了更好地理解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如何以任意顺序检索和删除元素?
答案 0 :(得分:2)
作为ElpieKay wrote in a comment,当前藏匿的所有内容都存储在引用 refs/stash
的reflog中。请参阅the gitglossary中“ref”和“reflog”的定义。请注意,master
和develop
等分支名称是一种引用,分别是全名refs/heads/master
和refs/heads/develop
的缩写。标签名称是另一种参考;标记v2.2
实际上是引用refs/tags/v2.2
。
大多数引用都以refs/
为前缀。事实上,各种HEAD - HEAD
本身,MERGE_HEAD
,CHERRY_PICK_HEAD
,ORIG_HEAD
等等 - 是唯一的例外情况,而且大多数那些< / em>不拥有 reflogs。 HEAD
是唯一能做到的人。
通常,reflog条目只是线性编号:HEAD@{1}
或master@{1}
是“HEAD
或master
在最近更新之前指向的提交”,{ {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}
后,所有较高的条目 - stash
,stash@{1}
等等 - 下拉一个,所以现在stash@{2}
已“弹出”,之前的stash
只是stash@{1}
。当然,您也可以stash
删除该特定条目,保持0到3并重新编号为5-and-up。请注意,任何特定存储的git stash drop stash@{4}
仅表示“应用,如果这似乎成功,则删除”。
请注意,并非完全偶然的是,每个reflog条目也都附有时间戳。您可以编写git stash pop
或master@{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。)