git prune何时确切地成为对象:为什么"git gc"被删除?不删除提交? [英] When exactly does git prune objects: why is "git gc" not removing commits?

查看:134
本文介绍了git prune何时确切地成为对象:为什么"git gc"被删除?不删除提交?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在上一门git课程,我想提一提,丢失的裁判直到运行git gc时才真正丢失.但是验证这一点,我发现事实并非如此.即使运行git gc --prune=all --aggressive之后,丢失的引用仍然存在.

I'm working on a git course and wanted to mention that lost refs are not really lost until running git gc. But verifying this, I found out that this is not the case. Even after running git gc --prune=all --aggressive the lost refs are still there.

很明显,我误解了一些东西.在说出课程中不正确的内容之前,我想弄清我的事实!这是一个示例脚本,说明了效果:

Clearly I misunderstood something. And before saying something incorrect in the course, I want to get my facts straight! Here is an example script illustrates the effect:

 #!/bin/bash

 git init

 # add 10 dummy commits
 for i in {1..10}; do
     date > foo.txt
     git add foo.txt
     git commit -m "bump" foo.txt
     sleep 1
 done;

 CURRENT=$(git rev-parse HEAD)
 echo HEAD before reset: ${CURRENT}

 # rewind
 git reset --hard HEAD~5

 # add another 10 commits
 for i in {1..10}; do
     date > foo.txt
     git add foo.txt
     git commit -m "bump" foo.txt
     sleep 1
 done;

此脚本将添加10个虚拟提交,将其重置为过去的5个提交,并添加另外10个提交.重置之前,它将打印当前HEAD的哈希值.

This script will add 10 dummy commits, reset to 5 commits in the past and add another 10 commits. Just before resetting, it will print the hash of it's current HEAD.

运行git gc --prune=all后,我会期望丢失CURRENT中的对象.但是,我仍然可以在该哈希上运行git show.

I would expect to lose the object in CURRENT after running git gc --prune=all. Yet, I can still run git show on that hash.

我确实了解到,在运行git reset并添加新的提交之后,我实际上已经创建了一个新分支.但是我的原始分支不再有任何引用,因此它不会显示在git log --all中.我想它也不会被推送到任何远程.

I do understand that after running git reset and adding new commits, I have essentially created a new branch. But my original branch no longer has any reference, so it does not show up in git log --all. It also would not be pushed to any remote I suppose.

我对git gc的理解是删除了这些对象.似乎并非如此.

My understanding of git gc was that is removes those objects. This does not seem to be the case.

为什么?而何时到底是git gc删除对象吗?

Why? And when exactly does git gc remove objects?

推荐答案

要修剪的对象必须满足两个条件.一个与日期/时间相关:它必须已经创建 1 足够长的时间才能成熟以进行收集. 足够长的时间"部分就是您使用--prune=all进行的设置:您将覆盖正常的至少两周大"的设置.

For an object to be pruned, it must meet two criteria. One is date/time related: it must have been created1 long enough ago to be ripe for collection. The "long enough ago" part is what you are setting with --prune=all: you're overriding the normal "at least two weeks old" setting.

第二个标准是您的实验出错的地方.要修剪,对象必须不可达.如 twalberg所述注释,实际上是通过Git的"reflog"条目引用了每个表面上被放弃的提交(因此也包含了它们相应的树和blob).

The second criterion is where your experiment is going wrong. To be pruned, the object must also be unreachable. As twalberg noted in a comment, each of your ostensibly-abandoned commits (and hence their corresponding trees and blobs) is actually referenced, through Git's "reflog" entries.

每个这样的提交都有两个引用日志条目:一个用于HEAD,一个用于在进行提交时HEAD本身所引用的分支名称(在这种情况下,是refs/heads/master的引用日志) ,即分支master).每个reflog条目都有其自己的时间戳记,并且git gc也会使reflog条目过期,尽管规则集比对象到期时默认的简单"14天"更为复杂. 2

There are two reflog entries for each such commit: one for HEAD, and one for the branch name to which HEAD itself referred at the time the commit was made (in this case, the reflog for refs/heads/master, i.e., branch master). Each reflog entry has its own time-stamp, and git gc also expires reflog entries for you, although with a more complex set of rules than the simple "14 days" default for object expiry.2

因此,git gc 可以首先删除所有保留旧对象的引用日志条目,然后修剪该对象.只是这里没有发生.

Hence, git gc could first delete all reflog entries that are keeping the old object around, then prune the object. It just is not happening here.

要手动查看,甚至删除reflog条目,请使用git reflog.请注意,通过运行git log-g/--walk-reflogs选项(以及一些其他显示格式选项),git reflog 显示条目.您可以运行git reflog --all --expire=all清除所有内容,尽管在手术刀可能更合适的情况下这是一种笨拙.使用--expire-unreachable可以提高选择性.有关此的更多信息,请参见 git log文档,当然还有 git reflog文档.

To view, or even delete, reflog entries manually, use git reflog. Note that git reflog displays entries by running git log with the -g / --walk-reflogs option (plus some additional display formatting options). You can run git reflog --all --expire=all to clear everything out, though this is a bludgeon when a scalpel may be more appropriate. Use --expire-unreachable for a bit more selectivity. For more about this, see the git log documentation and of course the git reflog documentation.

1 某些Unix-y文件系统根本不存储文件创建(出生")时间:stat结构的st_ctime字段是 inode更改时间,而不是创建时间.如果有创建时间,则在st_birthtimest_birthtimespec中. 3 但是,每个Git对象都是只读的,因此文件的创建时间也就是其修改时间.因此始终可用的st_mtime给出了对象的创建时间.

1Some Unix-y file systems do not store file creation ("birth") time at all: the st_ctime field of a stat structure is the inode change time, not the creation time. If there is a creation time, it is in st_birthtime or st_birthtimespec.3 However, every Git object is read-only, so the file's creation time is also its modification time. Hence st_mtime, which is always available, gives the creation time for the object.

2 git gc文档,但是我认为默认情况下,对于无法访问的提交,30天,对于可以访问的提交90天是一个不错的总结.但是,这里的 reachable 定义是不寻常的:它表示从引用的当前值中可引用,而此reflog保留了旧值.master的引用日志中,我们找到master所标识的提交(例如,1234567),然后查看从该特定地址是否可以访问master(例如,master@{27})的每个引用日志条目.提交(再次输入1234567).

2The exact rules are described in the git gc documentation, but I think By default, 30 days for unreachable commits and 90 days for reachable commits is a decent summary. The definition of reachable here is unusual, though: it means reachable from the current value of the reference for which this reflog holds old values. That is, if we're looking at the reflog for master, we find the commit that master identifies (e.g., 1234567), then see if each reflog entry for master (e.g., master@{27}) is reachable from that particular commit (1234567 again).

3 这种特殊的名称混淆是POSIX标准化人员带来的. :-) st_birthtimespec字段是struct timespec,它记录秒和纳秒.

3This particular name confusion is brought to you by the POSIX standardization folks. :-) The st_birthtimespec field is a struct timespec, which records both seconds and nanoseconds.

这篇关于git prune何时确切地成为对象:为什么"git gc"被删除?不删除提交?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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