我读了Git 不存储文件差异。如果这是真的,它如何支持文件回滚到以前的版本?如果它存储整个文件,则磁盘上的存储库空间必须增长到无法管理的大。Git 是否支持文件回滚和差异回到文件版本 1?它甚至支持与文件相关的版本控制概念吗?这(我相信)对于我理解 VCS/DVCS 和我的需求至关重要。我需要能够将我要签入的内容与以前的版本进行比较。
答案1
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 垃圾回收或较低级别的打包命令之一),Git 会将许多松散的对象收集到一个“打包文件”中。
包文件中的对象可以存储为普通压缩数据(与松散对象相同,只是与其他对象捆绑在一起),也可以存储为针对其他对象的压缩增量。增量可以链接到可配置的深度(pack.depth
),并且可以针对任何合适的对象进行制作(pack.window
控制 Git 搜索最佳增量基础的范围;如果这样做会产生良好的增量压缩,则可以将历史上不相关的文件的版本用作基础)。深度和窗口大小配置为增量压缩引擎提供的自由度通常会产生比 CVS 样式的简单一个版本针对下一个/上一个版本的“差异”压缩更好的增量压缩。
正是这种积极的增量压缩(与正常的 zlib 压缩相结合)通常可以使 Git 存储库(具有完整的历史记录和未压缩的工作树)比单个 SVN 检出(具有未压缩的工作树和原始副本)占用更少的空间。
查看Git 如何存储对象和打包文件部分Git 社区手册. 还有git pack-对象手册页。
* 你可以通过“重写历史记录”和以下命令告诉 Git 丢弃提交:git 重置,但即使在这种情况下,Git 也会暂时“保留”新丢弃的提交,以备您决定需要它们。请参阅git 引用日志和git 修剪。
答案2
您可以在同一页面上阅读:
...
因此,Git 没有明确记录源代码树以下任何级别的文件修订关系。
...
检查单个文件的更改历史记录比检查整个项目的更改历史记录稍微昂贵一些。要获取影响给定文件的更改历史记录,Git 必须遍历全局历史记录,然后确定每个更改是否修改了该文件。但是,这种检查历史记录的方法确实让 Git 能够以同样的效率生成单个历史记录,显示对任意一组文件的更改。例如,源树的子目录加上关联的全局头文件是一种非常常见的情况。
...
因此,您可以返回文件的先前修订版本并比较两个文件。
答案3
git 确实保存了文件的增量,但它将它们保存为整个文件树的增量。
要查看版本之间的差异,请执行以下操作之一:
- git diff- 显示上次签入版本与已更改但尚未
git add
运行的文件之间的差异。 - git diff --cached
git add
- 显示先前版本与已运行但尚未提交的所有文件之间的差异 - git diff 提交ID- 显示当前工作目录和上一次提交之间的差异,具体差异由 commitid 指定
- git diff 提交..提交b- 显示两个提交 a 和 b 之间的差异。提交也可以是分支或标签等符号名称。