git stash元素存储在哪里?数据结构真的是堆栈吗? [英] Where are the git stash elements stored? Is the data structure really a stack?

查看:204
本文介绍了git stash元素存储在哪里?数据结构真的是堆栈吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了更好地理解git stash,我想知道:git stash的元素存储在什么位置以及以什么数据结构存储?在堆栈中?在有序集合中?

To understand the git stash better, I would like to know: Where and in what data structure are the elements of the git stash stored? In a stack? In an ordered set?

详细信息:

所有文档,文章和书籍(除了 Git Internals 之外)都说git stash是堆栈.

Every documentation, article and book (except Git Internals) says that the git stash is a stack.

最近,我发现您可以从存储中以任意顺序检索和删除元素,这是个有用的功能.由于此功能和《 Git黑客指南》 ,在我看来该存储区由某个地方的按时间顺序排列的引用组成.但是,在.git/refs/stash中,仅以合并提交的形式存储最新的stash元素(还包含创建stash元素的日期).

Recently, I found out that you can retrieve and delete the elements in arbitrary order from the stash -- what a helpful feature. Because of this feature and A Hacker's Guide to Git, it seems to me that the stash rather consists of a chronologically ordered set of references somewhere. However, in .git/refs/stash only the latest stash element is stored, in form of a merge commit (which also contains the date the stash element was created).

还有另一个(

Is there another (top-secret pre-index stash-cache;) data structure holding all the stash elements? Or does git stash (list|pop|apply) retrieve the elements from its regular object store? How?

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

So what data structure do the stash elements form? Is the chronological order of the elements implicitly given by the date of the merge commits? If the elements are in fact stored in a stack, how does git retrieve and delete the elements in arbitrary order?

推荐答案

gitglossary中的"ref"和"reflog"的定义.请注意,像masterdevelop这样的分支名称是一种引用,并且分别是全名refs/heads/masterrefs/heads/develop的缩写.标签名称是另一种参考.标签v2.2确实是引用refs/tags/v2.2.

As ElpieKay wrote in a comment, all but the current stash are stored in the reflog for the reference refs/stash. See the definitions of "ref" and "reflog" in the gitglossary. Note that branch names like master and develop are one kind of reference, and are short for the full name refs/heads/master and refs/heads/develop respectively. Tag names are another kind of reference; the tag v2.2 is really the reference refs/tags/v2.2.

大多数引用都以refs/为前缀.实际上,各种HEAD(HEAD本身以及MERGE_HEADCHERRY_PICK_HEADORIG_HEAD等)是唯一的例外,大多数 都不是拥有更新. HEAD是唯一这样做的人.

Most references are prefixed with refs/. In fact, the various HEADs—HEAD itself, and MERGE_HEAD, CHERRY_PICK_HEAD, ORIG_HEAD, and so on—are the only exceptions, and most of those don't have reflogs. HEAD is the only one that does.

通常,引用日志条目只是简单地线性编号:HEAD@{1}master@{1}是"HEADmaster在其最新更新之前指向的提交",master@{2}是两步之前的提交, 等等. gitrevisions 中对此进行了描述.为了方便起见,可以使用@{0}引用 current 值:master@{0}master始终解析为相同的哈希ID.如果refs/stash引用的使用方式与其他引用相同,则它将作为队列而不是堆栈使用-但这不是使用的方式.相反,git stash代码会明确删除早期条目.

Normally, reflog entries are simply linearly-numbered: HEAD@{1} or master@{1} is "the commit to which HEAD or master pointed before its most recent update", master@{2} is the commit two steps ago, and so on. This is described in gitrevisions. For convenience, the current value can be referred-to with @{0}: master@{0} and master always resolve to the same hash ID. If the refs/stash reference were used in the same way as other references, it would work as a queue, rather than a stack—but it's not used that way. Instead, the git stash code explicitly deletes early entries.

由于编号始终是连续的,因此删除条目会导致所有较高编号下降1.例如,如果手动删除master@{5},则以前是master@{6}的现在是master@{5},以前是master@{7}的现在是master@{6},依此类推.

Since the numbering is always sequential, deleting an entry causes all the higher numbers to drop down by one. If you manually delete master@{5}, for instance, then what used to be master@{6} is now master@{5}, what used to be master@{7} is now master@{6}, and so on.

添加一个新条目,当然会使所有内容都向上推.因此,当您创建新存储库时,以前是stashstash@{0}的存储库现在是stash@{1}.以前是stash@{1}的现在是stash@{2},依此类推.对于其他引用,例如master,没有人称其为推送",这只是运行中的普通队列.

Adding a new entry, of course, pushes everything up one. So when you create a new stash, the one that used to be stash aka stash@{0} is now stash@{1}. The one that used to be stash@{1} is now stash@{2}, and so on. With other reflogs, like master, no one calls this "pushing", it's just the ordinary queue in action.

但是,一旦您删除 stash@{0} aka stash,所有更高的条目(stash@{1}stash@{2}等)将下降1,因此现在stash已被弹出",而以前的stash@{1}只是stash.当然,您也可以git stash drop stash@{4}删除该特定条目,保持0到3并重新编号5到up.请注意,任何特定藏匿处的git stash pop都仅表示应用,如果看起来成功,则放下".

Once you delete stash@{0} aka stash, though, all the higher entries—stash@{1}, stash@{2}, and so on—drop down by one, so now stash has been "popped" and the previous stash@{1} is just stash. Of course, you can also git stash drop stash@{4} to delete that particular entry, keeping 0-to-3 and renumbering 5-and-up. Note that git stash pop of any particular stash just means "apply and, if that seems to succeed, drop".

请注意(并非完全偶然),每个reflog条目都附加了时间戳.您可以编写master@{yesterday}master@{3.hours.ago},然后Git将根据时间戳找到适当的reflog条目的哈希ID. 1 因为隐藏标识符只是reflog条目,所以该语法也可以在这里工作. (我从未真正发现这在任何地方都有用,也许是因为我在工作时没有时间感,并且不记得现在是星期几的时间了,更不用说我早些时候做的事情了. .:-))要使用这些时间戳记, most 引用日志 expire :默认情况下,旧的reflog条目将在90天后消失,如果没有,则仅30天 2 但是,默认情况下,refs/stash本身不受此有效期限制.所有这些都是可配置的:请参见

Note, not entirely incidentally, that each reflog entry also has a time-stamp attached. You can write master@{yesterday} or master@{3.hours.ago} and Git will find the hash ID of the appropriate reflog entry, based on the time stamps.1 Because stash identifiers are just reflog entries, this same syntax works there. (I have never actually found this all that useful anywhere, perhaps because I have no sense of time when I am working and cannot remember what day of the week it is now, much less when I did something earlier. :-) ) To go with these time stamps, most reflogs expire: an old reflog entry will, by default, go away after 90 days, or just 30 days if the object it names is not reachable from the current value of the same reference.2 However, refs/stash itself is exempt from this expiration, by default. All of this is configurable: see all of the gc.reflogExpire settings in the git config documentation.

1 如果一天中多次更新参考,但每小时更新不超过一次,则@{yesterday}表示@{24.hours.ago}.如果每小时更新一次以上,则再乘以60:@{1440.minutes.ago}.如果每分钟更新一次以上,请再次乘以60:@{86400.seconds.ago}.分辨率没有比这更好的了.

1If you updated the reference several times in a day but not more than once per hour, @{yesterday} means @{24.hours.ago}. If you updated more than once per hour, multiply by another 60: @{1440.minutes.ago}. If you updated more than once per minute, multiply by 60 again: @{86400.seconds.ago}. The resolution does not go any finer than that.

2 例如,这就是Git保留30天,但最终清除由git rebase放弃的旧提交的方式. 可达到性是由存储库中的标签,提交和树对象形成的有向无环图或DAG提供的关键概念. (Blob是DAG中的 ,但由于它们始终是叶节点而没有扩展它.因此,Blob本身可能是可到达或不可到达的,但它不会影响任何 other 对象.)

2This is how Git retains for 30 days, but eventually purges, old commits that were abandoned by a git rebase, for instance. Reachability is a key concept provided by the Directed Acyclic Graph or DAG formed by the tags, commits, and tree objects in the repository. (Blobs are in the DAG but have no part in extending it as they are always leaf nodes. Hence a blob may itself be reachable or unreachable, but it never affects the reachability of any other object.)

这篇关于git stash元素存储在哪里?数据结构真的是堆栈吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆