场景
想象一下,我被迫使用一些总是存储在.zip
文件中的文件。 zip中的一些文件是小文本文件并经常更改,而其他文件更大但幸运的是相当静态(例如图像)。
如果我想将这些zip文件放在git
存储库中,每个zip都被视为一个blob,所以每当我提交时,存储库的大小都会增加zip文件...即使只有一个小文本文件发生变化!
为什么这是现实的
MS Word 2007/2010 .docx
和Excel .xlsx
文件是ZIP文件...
我想要的是
是否有任何机会告诉git
不将拉链视为文件,而是作为目录并将其内容视为文件?
优点
但是,它说不行吗?
我意识到如果没有额外的元数据,这将导致一些歧义:在git checkout
git将不得不决定是否将foo.zip/bar.txt
创建为常规目录或zip文件中的文件。但是,我认为这可以通过配置选项解决。
两个想法如何完成(如果它还不存在)
minizip
或IO::Compress::Zip
等库这不存在,但它可以很容易地存在于当前框架中。正如git在执行diff时显示二进制或ascii文件的行为不同,可以通过配置界面告诉它对某些文件类型提供特殊处理。
如果您不想更改代码库(虽然这是一个很酷的想法),您也可以使用pre-commit and post-checkout hooks解压缩并存储文件,然后将它们返回到.zip,为自己编写脚本。在结账时说。您必须将操作限制为仅由git add
指定的那些文件blob / index。
无论哪种方式都是一些工作 - 这只是一个问题,其他git赞扬是否知道发生了什么,并发挥得很好。
不确定是否还有人对这个问题感兴趣。我面临同样的问题,这是我使用git文件过滤器的解决方案。
编辑:首先,我可能不会说清楚,但这是OP的问题的答案!在评论之前阅读整个句子。此外,感谢@Toon Krijthe提供的建议,以澄清解决方案。
我的解决方案是使用过滤器将zip文件“扁平化”为单片扩展(可能是巨大的)文本文件。在git add / commit期间,zip文件将自动扩展为此文本格式以进行正常的文本区分,并且在结帐时,它会再次自动压缩。
文本文件由记录组成,每个记录代表zip中的文件。所以你可以认为这个文本文件是原始zip的基于文本的图像。如果zip中的文件是契约中的文本,则将其复制到文本文件中;否则,在复制到文本格式文件之前,它是base64编码的。这使文本文件始终保持为文本文件。
虽然这个过滤器不会使zip中的每个文件成为blob,但是文本文件是逐行映射的,这是diff的单位,而二进制文件的更改可以通过更新它们对应的base64来表示,我认为这相当于OP想象的是什么。
有关详细信息和原型代码,您可以阅读以下链接:
此外,相信这个激发了我这个解决方案的地方:Description of how file filter works
使用bup(在GitMinutes #24中详细介绍)
它是唯一一个用于处理大型(甚至非常大)文件的类似git的系统,这意味着每个版本的zip文件只会增加其delta的repo(而不是完整的附加副本)
结果是一个实际的git repo,一个普通的Git命令可以读取。
我详细介绍了bup
在“git with large files”中与Git的不同之处。
任何其他解决方法(如git-annex
)并不完全令人满意,详见“git-annex
with large files”。
http://tante.cc/2010/06/23/managing-zip-based-file-formats-in-git/
(注意:根据Ruben的评论,这只是关于获得适当的差异,而不是关于提交解压缩的文件。)
打开〜/ .gitconfig文件(如果已经存在则创建)并添加以下节:
[diff“zip”] textconv = unzip -c -a
它的作用是使用“unzip -c -a FILENAME”将zipfile转换为ASCII文本(解压缩-c解压缩到STDOUT)。接下来是创建/修改文件REPOSITORY / .gitattributes并添加以下内容
* .pptx diff = zip
它告诉git使用配置中的zip-diffing描述来计算给定掩码的文件(在这种情况下,所有内容都以.pptx结尾)。现在git diff自动解压缩文件并区分ASCII输出,这比仅仅“二进制文件不同”好一点。另一方面,对于pptx文件的相应XML的复杂混乱,它没有多大帮助,但对于包括文本的ZIP文件(例如源代码存档),这实际上非常方便。
通常,应用程序的预压缩文件存在问题,因为他们希望zip压缩方法和文件顺序是他们选择的。我相信开放式办公.odf文件有这个问题。
也就是说,如果你只是使用any-old-zip作为保持一起的方法,你应该能够创建一些简单的别名,这些别名将在需要时解压缩并重新压缩。最新的Msysgit(又名Git for Windows)现在在shell代码端同时具有zip和unzip,因此您可以在别名中使用它们。
我目前正在开发的项目使用zip作为主要的本地版本控制/存档,所以我也试图获得一组可行的别名,用于将这些数百个zips吸入git(并将它们再次取出;-) so同事们很开心。
与Rezip类似,Zippey by sippey允许使用git以更好的方式处理ZIP文件。
在添加/提交基于ZIP的文件时,在将其添加到索引/提交之前,Rezip将其解压缩并重新打包而不进行压缩。在未压缩的ZIP文件中,归档文件在其内容中显示为原样(以及每个文件之前的一些二进制元信息)。如果这些归档文件是纯文本文件,则此方法将与git很好地配合使用。
Rezip优于Zippey的主要好处是存储在存储库中的实际文件仍然是ZIP文件。因此,在许多情况下,它仍然可以与相应的应用程序(例如Open Office)一起工作,即使它是在不经过重新打包压缩过滤器的情况下获得的。
在您的系统上安装过滤器:
mkdir -p ~/bin
cd ~/bin
# Download the filer executable
wget https://github.com/costerwi/rezip/blob/master/Rezip.class
# Install the add/commit filter
git config --global --replace-all filter.rezip.clean "java -cp ~/bin Rezip --store"
# (optionally) Install the checkout filter
git config --global --add filter.rezip.smudge "java -cp ~/bin Rezip"
通过在<repo-root>/.gitattributes
文件中添加这些行,在存储库中使用过滤器:
[attr]textual diff merge text
[attr]rezip filter=rezip textual
# MS Office
*.docx rezip
*.xlsx rezip
*.pptx rezip
# OpenOffice
*.odt rezip
*.ods rezip
*.odp rezip
# Misc
*.mcdx rezip
*.slx rezip
textual
部分是这样的,这些文件实际上显示为差异中的文本文件。