场景
想象一下,我被迫处理一些总是存储在.zip
文件中的文件。ZIP文件中的一些文件是小文本文件,经常更改,而其他文件则较大,但幸运的是相当静态(例如图像)。
如果我想把这些ZIP文件放在Git仓库中,每个ZIP文件都被视为一个blob,所以每当我提交时,仓库就会按ZIP文件的大小增长......即使里面只有一个小文本文件发生了变化!
为什么这是现实的
Microsoft Word 2007/2010 .docx
和Excel .xlsx
文件是ZIP文件...
"我想要的"
有没有一种方法可以告诉Git不要把ZIP文件当作文件,而是当作目录,把它们的内容当作文件?
优点
- 更小的存储库大小,即更快的传输/备份
- Display changes with Git to ZIP files将自动工作
- 但你说这行不通 *
我意识到,如果没有额外的元数据,这将导致一些歧义:在git checkout
上,Git必须决定是否将foo.zip/bar.txt
创建为常规目录中的文件或ZIP文件。然而,我认为这可以通过配置选项来解决。
两个想法如何可以做到(如果它还不存在)
- 使用Git内部的
minizip
或IO::Compress::Zip
等库 - 以某种方式添加文件系统层,这样Git实际上会将ZIP文件视为开始的目录
8条答案
按热度按时间wvyml7n51#
这是不存在的,但它很容易在当前的框架中存在。就像Git在执行diff时显示二进制或ASCII文件的行为不同一样,它可以通过配置界面被告知对某些文件类型提供特殊处理。
如果你不想改变代码库(虽然这是一个很酷的想法),你也可以自己编写脚本,使用pre-commit and post-checkout hooks解压并存储文件,然后在 checkout 时将它们返回到.zip状态。你必须将操作限制在
git add
指定的那些文件blob/索引上。无论哪种方式都需要做一些工作--这只是一个问题,即其他Git命令是否知道发生了什么并能很好地运行。
vddsk6oq2#
使用**bup(详见GitMinutes #24)
它是唯一一个被设计用来处理大型(甚至是非常非常大)文件的类git系统,这意味着每个版本的zip文件只会从它的delta增加repo(而不是一个完整的额外副本)
结果是一个实际的git repo,一个普通的Git命令可以读取。
我在“git with large files”中详细介绍了
bup
与Git的区别。任何其他解决方法(如
git-annex
**)都不完全令人满意,详见“git-annex
with large files”。bvjxkvbb3#
Zippey -使用 *Git文件过滤器 * 的解决方案
我的解决方案是使用过滤器将ZIP文件“扁平化”为一个整体的,扩展的(可能是巨大的)文本文件。在
git add
/commit
过程中,ZIP文件将自动扩展为这种文本格式,以进行正常的文本区分,并在结帐过程中,它会自动再次压缩。文本文件是由记录组成的,每个记录代表ZIP文件中的一个文件。因此,您可以认为此文本文件是原始ZIP文件的基于文本的图像。如果ZIP文件中的文件确实是文本,则复制到文本文件中;否则,在复制到文本格式文件之前,它是Base64编码的。这使文本文件始终是文本文件。
虽然这个过滤器并没有把ZIP文件中的每个文件都变成一个blob,但是文本文件被Map为一行到一行--这是diff的单位--而二进制文件的更改可以通过其对应的Base64的更新来表示。我认为这与OP所想象的是等价的。
有关详细信息和原型代码,您可以阅读以下链接:
Zippey Git file filter
此外,感谢启发我这个解决方案的地方:Description of how file filter works
a0zr77ik4#
来自 * Managing ZIP-based file formats in git *:
注意:根据Ruben的评论,这只是关于获得适当的diff,而不是关于提交解压缩文件。
打开您的
~/.gitconfig
文件(如果还不存在则创建)并添加以下节:它使用“unzip -c -a FILENAME”将zip文件转换为ASCII文本(unzip -c unzips to STDOUT)。
它告诉git使用配置文件中的zip-diffing描述来匹配给定的掩码(在本例中,所有文件都以.pptx结尾)。现在git diff会自动解压缩文件并区分ASCII输出,这比“二进制文件不同”好一点。另一方面,对于pptx文件对应的XML的复杂混乱,它没有太大的帮助,但是对于包含文本的ZIP文件(例如源代码归档),这实际上是非常方便的。
pb3skfrl5#
java工具ReZipDoc,类似于Zippey by sippey,允许使用Git以更好的方式处理ZIP文件。
工作原理
当添加/提交一个基于ZIP的文件时,Rezip在将其添加到索引/提交之前,将其解压缩并重新压缩。在未压缩的ZIP文件中,归档文件在其内容中显示为 * 原样 *(在每个文件之前都有一些二进制 meta信息)。如果这些归档文件是纯文本文件,则此方法将与Git配合使用。
福利
Rezip优于Zippey的主要优点是,存储在存储库中的实际文件仍然是ZIP文件。因此,在许多情况下,它仍然可以与相应的应用程序(例如Open Office)一起工作 * as-is *,即使它是在没有经过重新打包压缩过滤器的情况下获得的。
如何使用
在系统上安装过滤器:
在您的存储库中使用过滤器,方法是向
<repo-root>/.gitattributes
文件中添加如下行:textual
部分是这样的,这些文件实际上在差异中显示为文本文件。5t7ly7z56#
以下是我的方法:
.gitattributes
文件中应用过滤器:.gitattributes
文件添加一些二进制处理:.gitignore
文件中添加一些内容:1.一些配置:
1.安装Git LFS
1.通过发出一次
git lfs install
命令来准备LFS。1.设置Git过滤器。
1.通过发出
git config core.hooksPath .githooks
命令安装钩子。1.通过发出命令
.githooks/post-checkout
应用checkout钩子一次。1.通过发出命令
git add -A
应用过滤器一次。有关示例,请参见此处:* 一个月一次 *
已知问题
wgxvkvu97#
应用程序的预压缩文件经常会有问题,因为他们希望ZIP压缩方法和文件顺序是他们选择的。我相信OpenOffice.odf文件有这个问题。
也就是说,如果你只是使用任何旧的ZIP文件作为一种方法来保持东西在一起,你应该能够创建一些简单的别名,这些别名将在需要时解压缩和重新压缩。最新的MSysGit(又名Git for Windows)现在在shell代码端有zip和unzip,所以你可以在别名中使用它们。
我目前正在做的项目使用ZIP文件作为主要的本地版本控制/存档,所以我也在尝试获得一组可行的别名,用于将这数百个ZIP文件吸入Git(并再次将它们取出;(2)让同事们开心。
piok6c0g8#
在Bash中有@callegar的Rezip实现。
我将过滤器添加到仓库的配置中:
注意到
zip
工具不适用于普通的Git-for-Windows安装,尽管unzip
是。所以我用perl写了一个替代品:它非常慢,但还算可以工作。我想有人可以在此基础上用perl重新实现整个
rezip
。