尽管GIT不会存储文件增量,但您是否仍可以回滚到以前的文件版本(无限次数?)


14

我读过,Git不存储文件增量。如果是这样,它如何支持文件回滚到以前的版本?如果要存储整个文件,则磁盘上的存储库空间必须增加到难以管理的程度。Git是否支持文件回滚和diff返回文件版本1?它甚至支持与文件相关的版本控制概念吗?(我认为)这对于我了解VCS / DVCS和我的需求至关重要。我需要能够将要检查的内容与以前的版本进行比较。

Answers:


44

Git不会自行丢弃信息 *。每个文件的所有先前版本始终可用于还原,差异,检查等。

全树与个人文件

您可能想调和的是访问单个文件的旧版本的想法,而不是Git的历史记录模型专注于整个树的事实。整树的版本控制确实需要做更多的工作才能看到(例如)十个更改前与十个完整树更改前foo.c存在的版本foo.c

# 10 foo.c-changes ago
git show $(git rev-list -n 10 --reverse HEAD -- foo.c | head -1):foo.c

# 10 whole-tree-changes ago
git show HEAD~10:foo.c

面向树的好处,主要是将提交作为对整个树的各个部分进行的相互依赖更改的单位进行查看的能力,通常大大超过了额外的键入(可以通过别名,脚本等减轻)和CPU时间花在挖掘过去的提交上。

储存效率

当一个新对象(例如,一个以前看不见的文件)进入系统时,它将以普通(zlib)压缩方式存储为“松散对象”。当积累了足够多的松散对象(基于gc.auto配置选项;或者当用户运行git gc或较低级别的打包命令之一)时,Git会将许多松散对象收集到一个“打包文件”中。

打包文件中的对象可以存储为纯压缩数据(与松散对象相同,只是与其他对象捆绑在一起),也可以存储为针对其他对象的压缩增量。可以将Delta链接到可配置的深度(pack.depth),并可以针对任何合适的对象制作pack.windowDelta (控制Git搜索最佳delta底数的范围;如果这样做会产生良好的增量压缩)。深度和窗口大小配置赋予增量压缩引擎的纬度通常会导致比CVS样式的简单单版本对下一个/上一个版本的“差异”压缩更好的增量压缩。

正是这种主动的增量压缩(与常规zlib压缩相结合)通常可以使Git存储库(具有完整的历史记录和未压缩的工作树)比单个SVN检出(具有未压缩的工作树和原始副本)占用更少的空间。

请参阅《Git如何存储对象》《 Git社区手册》的Packfile部分。也是git pack-objects手册

*您可以通过“重写历史记录”和git reset之类的命令告诉Git丢弃提交,但是即使在这种情况下,Git也会“挂在”新丢弃的提交上一段时间,以防万一您决定需要它们。参见git refloggit prune


3
+1仅代表您提供的信息的数量和详细信息。
塔玛拉·威斯曼

3
另外,由于Git使用文件快照而不是增量快照,因此回溯历史记录实际上很容易。假设您需要查看20次提交中的文件。如果使用增量,则需要撤消20个变更集;使用快照,您只需获取正确的快照。您的历史越长,优势就越大。如果你想看到的当前版本和一个之间的差异,它只是一个单一的差异,而不是决定什么是已经完成,百废待兴,重做等
内森龙

克里斯(Chris),您似乎对Git内部有相当不错的了解。您有机会在这个问题上摇摆吗?stackoverflow.com/questions/5176225/...
内森龙

@ChrisJohnsen请帮助我理解这一点。根据您所说的,Git可以获得比Subversion相似(或更好)的存储效率吗?我知道,如果我多次提交几乎没有任何更改的文件,则可以在100MB中保存价值1GB的数据。Git可以这样做吗?
Alireza Noori

@AlirezaNoori:这完全取决于数据的性质和捕获的更改(文件大小,文件的可压缩性,更改的大小和位置等)。这样的事情肯定应该可行(具体取决于具体情况)。一般而言,与SVN服务器使用的严格按时间顺序排列的增量相比,Git的pack文件可以从更多的增量压缩基础中进行选择(使用?我不遵循SVN开发…)。如果您有特定的问题,则应考虑提出一个包含所有相关细节的新问题。
克里斯·约翰森

1

可以在同一页面上阅读:

...

因此,Git不会在源代码树下的任何级别显式记录文件修订版本关系。

...

检查单个文件的更改历史记录比整个项目要贵一些。为了获得影响给定文件的更改历史,Git必须遍历全局历史,然后确定每个更改是否修改了该文件。但是,这种检查历史记录的方法的确可以让Git以相同的效率生成单个历史记录,以显示对任意文件集的更改。例如,源树的子目录加上相关的全局头文件是很常见的情况。

...

因此,您可以返回文件的先前版本并比较两个文件。


1

git实际上确实保存了文件增量,但是将它们另存为整个文件树的增量。

要查看版本之间的差异,请执行以下一项操作:

  1. git diff-显示最后签入的版本与已更改但尚未在其上git add运行的文件之间的差异。
  2. git diff --cached-显示先前版本与已git add运行但尚未提交的所有文件之间的差异
  3. git diff commitid-显示当前工作目录和使用commitid指定的先前提交之间的差异
  4. git diff commita..commitb-显示两个提交a和b之间的差异。提交也可以是符号名称,例如分支或标记。

这个答案不是真的正确。所有这些命令都可以应用于任意文件集以及整个树-只需在文件末尾添加文件名...
naught101
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.