我们团队中的某个人将一系列提交推送到孤立的远程存储库。也就是说,第一次提交没有父级。随后的是第一个的后代。分支上也没有名字。从图形上看,它看起来像这样
master
o Commit #4
| (no branch)
o commit #3 o commit #7
| |
o commit #2 o commit #6
| |
o commit #1 o commit #5
我想删除提交5-7。我尝试在commit 5创建一个分支。然后,提交6和7被列为在该分支上。然后,我尝试修剪分支,但无济于事。
我该怎么做?
更新:我认为问题与不匹配的分支名称有关。开发人员以某种方式将远程控制器上的新分支命名为master。最初已经有一位大师,仍然存在于我当地。因此,(我使用GitExt)在本地查看存储库时,我认为它混淆了GitExt并显示本地分支没有任何名称。当我将master分支重置回远程的原始分支时,新分支不再有任何引用并消失。问题解决了,我想。
答案 0 :(得分:3)
Sukima's question-comment是了解所有这一切的关键。
在Git存储库中,提交图(DAG)表示为提交对象的集合。像往常一样,每个对象通过其哈希ID进行标识,并且每个提交在其中都有一些父对象ID(零或更多,但通常为1)。 Git使用父链接来构造图形,但为了开始这个图形构建过程,它必须有一些方法来识别"起点"。 (其他版本控制系统,包括Mercurial,使用其他技术,不需要这个起点列表。)
这些起点是Git的参考。两个最常见的参考文献是分支和标签名称,但还有其他"常规"引用,所有引号都在以refs/
开头的名称下,以及一些特殊的引用,如HEAD
(当HEAD
分离时)和FETCH_HEAD
(在一个已运行git fetch
的存储库中{{ 1}})。还有一些额外的特殊引用:索引(也称为暂存区域,也就是缓存)可以直接引用" blob" (存储在存储库数据库中的文件对象 - 这些文件对象不参与提交图,但它们都是相同整体存储方案的一部分。)
创建一个对象然后放弃它是很正常的。提交和blob是最典型的,但四种对象类型中的任何一种都可以通过此过程。例如,当我们将它们复制到git commit --amend
或git rebase
的新提交时,我们放弃旧提交。 1 当我们git add
文件时,我们放弃blob对象,然后意识到它还没有完成,再进行编辑,然后git add
再次再提交。每个git add
将文件本身作为blob对象复制到存储库中,但在我们git commit
结果之前,它仅通过索引引用,并重新add
新版本会覆盖旧索引条目。
Git可以(有时会)完全扫描每个存储库对象,它会找到没有可能导致它们的起始点的对象。这些有时被称为无法访问的对象。 2 执行此操作的两个面向用户的命令 - 这些仍然非常维护 - 对大多数用户通常不是必需的 - 是存储库一致性检查器git fsck
和垃圾收集器 git gc
。因为他们做了这种全扫描,所以它们相对较慢。 3
因为它很慢,所以在后台完成自动垃圾收集":各种命令根据需要自动关闭git gc
,以丢弃未引用/不可达的提交和文件。这意味着后台清理可以与正常的Git活动竞争,这可以创建尚未引用的 new 对象,但是一旦命令完成,它就会立即生成。例如,GC可能与git commit
命令同时运行。如果GC在添加到分支之前发现了新创建的提交,并且删除了提交,那将是不好的。因此,为了安全起见,自动GC可以避免删除在过去14天内创建的任何内容:默认情况下,这会花费git commit
336小时来完成,这通常应该是足够的时间。 : - )
您始终可以通过其原始哈希ID找到任何现有的Git对象:Git如何访问每个对象,无论是在慢速全扫描操作中,还是枚举存储库中的每个ID,还是在以起点开始的更快操作,例如分支或标记引用。因此,如果提交确实无法访问,但 仍在存储库中,则可以通过其哈希ID查看它们。但最终,垃圾收集器将运行和它们将至少14天。此时,GC将删除它们将永远消失。 4
通常,您不需要关心其中的任何内容,但如果您不小心将敏感内容(例如明文密码或密钥或证书)放入存储库,则可能需要更快地删除它。这很难(见脚注),当你注意到谷仓门打开时,无论如何都可能克隆了马匹, 5 因此明智的做法是使证书无效,即使你设法找到并删除有问题的Git对象。
1 这些放弃的提交通常通过 reflogs 保留。每个普通refs/
名称空间参考有一个reflog,加上特殊HEAD
引用的一个大的。默认情况下,reflog中的项目至少可以使用30天,有时最长可达90天。 (两个时间值都是可配置的:请参阅gc.reflogExpire
和gc.reflogExpireUnreachable
。)但最终这些值也会过期,之后它们指向的对象可能会变为真正未引用的,因此也是GC的候选对象。
2 单词 unreferenced 可用于专门讨论没有直接引用的提交或其他对象,单词 unreachable 用于例如另一个提交引用的提交,但其他提交没有引用 it 。也就是说,在视觉上,我们可能会:
A--B--C--D <-- master
\
E--F <-- branch
\
G--H
最后两次提交G--H
根本没有名称,但我们可能只调用H
未引用,而两者都无法访问。但是Git对此不一致:git fsck
使用悬空这个词来描述提交H
。
3 这个GC过程让人想起一些编程语言&#39; &#34;标记和扫描&#34; GC。例如,看看很多Lisp实现,一直追溯到1959年。另见Wikipedia page on GC in programming languages。 Git的GC不使用(也不希望)引用计数,也不使用任何类型的实时动态实时GC系统,因为GC主要可以在后台运行,只需短时间锁定包文件。当然,Git的对象形成一个DAG,根据定义,它不包含循环,与Lisp数据结构不同。尽管如此,标记和扫描简单而有效,并且在这里运行良好。
4 这掩盖了压缩的对象。对象可以松散,在这种情况下,它们以压缩形式存储,但存储在单个文件中,或者压缩。打包的对象一起存储在一个文件中,其名称以.pack
结尾。 (这些.pack
文件可以有多个实例,每个文件都是自包含的。)如果需要,打包的对象仍然可以进行GC编辑,但这并不容易:包必须<使用git repack
重新打包。新包不会保留未引用的对象(git repack
称它们为“无法访问”#34;它的含义略有不同)。如果删除了旧的包文件,那么最终会丢弃该对象。但是,通过添加<name>.keep
文件,您可以将某些包标记为珍贵; 永远不会自动删除。
请注意,打包对象的主要目的是让它们更快更慢地访问(以复杂的方式,尝试更快地保留更新的对象),同时 delta压缩它们彼此相对在包内缩小磁盘空间使用量。垃圾收集器git gc
通常会自动为您处理所有这些。
5 正常的普通git clone
克隆引用/可达对象。但即使秘密或敏感文件总是无法访问,对于知道其中一个提交ID的攻击者来说,使用Git传输来访问该对象或有关该对象的信息也是可能的。请参阅the description of known transfer data leaks in the Git documentation。
答案 1 :(得分:1)
任何分支都不会引用的提交将被git垃圾收集器删除。无需做任何事情。