git可以将zip文件视为目录,将zip内部的文件视为blob吗?


73

场景

想象一下,我被迫使用总是存储在其中的某些文件 .zip文件文件。zip内的某些文件是小的文本文件,并且经常更改,而其他文件则较大,但幸运的是,它们是静态的(例如图像)。

如果我想将这些zip文件放在 git存储库中,则每个zip都被视为一个blob,因此每当我提交存储库时,该zip文件的大小都会增加...即使内部只有一个小文本文件发生了变化!

为什么这很现实

MS Word 2007/2010.docx和Excel.xlsx文件是ZIP文件...

我想要的是

有没有机会告诉git您不要将zip视为文件,而是将目录视为目录并将其内容视为文件?

优点

但这行不通,你说?

我意识到,没有额外的元数据将导致一定程度的歧义:在git checkoutgit上,必须决定要创建foo.zip/bar.txt为常规目录中的文件还是zip文件。但是,我认为这可以通过配置选项解决。

有两个想法如何实现(如果尚不存在)

  • 使用诸如gitminizipIO::Compress::Zipgit内部的库
  • 以某种方式添加文件系统层,以便git实际上将zip文件视为目录以

2
与该方案.docx文件是有道理的,但在其他许多情况下,你可能要考虑使用Git通常跟踪单个文件,只有建设所产生的.zip使用像一个合适的构建工具make
pixelistik

考虑到两个看上去互不相同的zip文件可以保存完全相同的数据(例如,一个文本文件以两种不同的压缩级别压缩了两次),这变得非常棘手。虽然很容易用很少的信息来表示两个版本的解压缩文件之间的差异,但是我猜想用很少的信息来表示两个版本的归档文件之间的差异(本质上是git必须要做的) -不重要的。
HelloGoodbye 2013年

您是否最终得到了Jeff的答案的解决方案或其他任何东西?我想知道除tar存档,其他内容基本相同,应该会产生一个兼容的答案……
Tobias Kienzler

SAP的信息设计工具(IDT)为其UNX格式创建了类似的文件结构。它也是递归的:它包含一个BLX文件和一个DFX文件,它们都是存档,分别对应于“业务层”和“数据基础”。我也想有一个解决方案。
Craig

Jetbrains内置的VCS确实允许您查看zip类型的文件。非常有用,但是需要您在IDE中查看例如PR。既然微软已经接管了,我们可能也会在github pr diff中看到这一点。
森特

Answers:


24

它不存在,但是在当前框架中很容易存在。就像git在执行diff时显示二进制文件或ascii文件的行为有所不同一样,可以通过配置界面告知git对某些文件类型提供特殊处理。

如果您不想更改代码库(尽管这是个不错的主意),也可以使用pre-commit和check-out挂钩解压缩并存储文件,从而自己编写脚本,然后在结帐时将其恢复为.zip状态。您必须将操作限制为仅由指定的那些文件blob /索引git add

无论哪种方式都需要一些工作-只是其他git命令是否了解正在发生的事情并可以很好地播放的问题。


钩子看起来确实是个不错的方向。我简短地考虑了一下,但是不确定是否可以。预提交挂钩可以同时修改文件系统和暂存区吗?
乔纳斯·海德堡

1
@Jonas您是否最终会这样做,您是否有机会发布可行的解决方案?我希望以git有用的方式跟踪对电子表格的更改,而CSV恰恰不适合我们的目的。
鲁本

请注意,如果使用脚本将已归档文件解压缩,然后再将其提交到存储库,并在签出后再次压缩文件,则即使在归档内部存储的文件未更改的情况下,紧接在检出之后的提交也很可能会修改归档文件。 。
HelloGoodbye 2013年

2
我只是写了一些钩子来做到这一点。仍然在粗糙的边缘上工作,但可能会有所帮助:github.com/ckrf/xlsx-git
katriel 2015年

14

Zippey-使用git文件过滤器的解决方案

我的解决方案是使用过滤器将zip文件“拉平”为一个整体的,扩展的(可能很大)的文本文件。在git add/期间commit该zip文件将自动扩展为该文本格式,以进行正常的文本对比;在结帐期间,该文件会自动再次压缩。

文本文件由记录组成,每个记录代表zip中的一个文件。因此,您可以认为此文本文件是原始zip的基于文本的图像。如果zip中的文件确实是文本,则将其复制到文本文件中;否则,它是base64编码的,然后再复制到文本格式文件中。这样可以使文本文件始终为文本文件。

尽管此过滤器不会使zip中的每个文件都成为斑点,但文本文件会逐行映射(这是diff的单位),而二进制文件的更改可以通过更新其相应的base64来表示。我认为这相当于OP的想象。

有关详细信息和原型代码,您可以阅读以下链接:

Zippey Git文件过滤器

另外,还要感谢激发我这一解决方案的地方: 关于文件过滤器工作原理的描述


如果您有任何疑问或任何建议,请让我知道此过滤器仍在开发中。
Sippey 2014年

1
我尝试了一下,我认为它应该对我来说很好。我只想在文档中添加一些内容,即必须修改文本文件列表zippey.py以包括希望zippey.py识别为文本文件的任何文件类型。
mteng 2014年

如此庞大的文件对许多工具都不友好。我特别考虑github 50 MB限制
PPC,

我不喜欢单片文件,因为它会生成太大而无法推送到github(100MB)的文件,并且不允许进行精细跟踪
PPC

1
值得注意的是LICENSE,您的存储库中没有文件或任何等效文件。无许可证=保留所有权利
user5532169 '18

12

使用bup(在GitMinutes#24中详细介绍)

它是唯一的git-like系统专门用来对付大(甚至是非常非常大)文件,这意味着一个zip文件的每个版本将只从它的增量增加(而不是一个完整的额外副本)回购

结果是常规的Git命令可以读取的实际git repo。

我将详细介绍bupGit与“ git with large files ”的区别。


git-annex如“git-annex使用大文件”中所述,任何其他解决方法(例如)都不是完全令人满意的。


1
这似乎非常适合于非常大的文件,该场景更适合于压缩了诸如docx和xlsx(通常很小)之类的XML。使用bup可以得到较小的repo大小,但是可以区分XML中的实际更改吗?
鲁本

@Ruben这适用于大小或数量较大的文件。但这与git在diff方面并没有太大区别。
VonC

看起来很有趣,但是您可以将其与实际的git repo一起使用吗?
kutschkem 2015年

@kutschkem我不这样认为:bup仓库是git仓库raw.githubusercontent.com/bup/bup/master/DESIGN),但是相反的说法似乎并不正确。
VonC

7

http://tante.cc/2010/06/23/managing-zip-based-file-formats-in-git/

(注意:根据Ruben的评论,这仅是获得适当的差异,而不是提交未压缩的文件。)

打开〜/ .gitconfig文件(如果尚不存在,则创建)并添加以下节:

[diff“ zip”] textconv =解压缩-c -a

它的作用是使用“ unzip -c -a FILENAME”将您的zip文件转换为ASCII文本(unzip -c解压缩为STDOUT)。接下来是创建/修改文件REPOSITORY / .gitattributes并添加以下内容

* .pptx diff = zip

它告诉git对配置给定掩码的文件使用config中的zip-diffing描述(在这种情况下,所有以.pptx结尾的文件)。现在,git diff自动解压缩文件并比较ASCII输出,这比“二进制文件不同”要好一点。另一方面,对于pptx文件的相应XML所造成的混乱,它并没有多大帮助,但是对于包含文本的ZIP文件(例如源代码档案)来说,这实际上非常方便。


1
但是,这仅与获得适当的差异有关,而不是与提交未压缩的文件有关。–
Ruben

谢谢。这回答了我要解决的问题,即在git diffing时显示gzip文件中的文本文件的更改。我曾经使用[diff "gzip"] = zcat*.gz diff=gzip
spazm '17

5

重新压缩 ReZipDoc,类似于由sippey Zippey,允许处理与git的一个更好的方式ZIP文件。

这个怎么运作

添加/提交基于ZIP的文件时,在将其添加到索引/提交之前,Rezip将其解压缩并重新打包而不进行压缩。在未压缩的ZIP文件中,已归档的文件在其内容中按原样显示(以及每个文件之前的一些二进制元信息)。如果这些归档文件是纯文本文件,则此方法可与git很好地配合使用。

好处

与Zippey相比,Rezip的主要好处是,存储在存储库中的实际文件仍然是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部分是使这些文件实际上显示为差异列表的文本文件。


听起来真酷!我已经有一段时间没有这个需求了,所以从没去实现任何东西,但是我一定会尝试的。
乔纳斯·海德堡

2

我认为您将需要将zip文件安装到文件系统。我没有用过,但是考虑一下保险丝:

http://code.google.com/p/fuse-zip/

还有适用于Windows和Linux的ZFS:

http://users.telenet.be/tfautre/softdev/zfs/


如果我正确理解的话,fuse-zip可以在文件系统和git之间分层,但是zfs必须内置在其中 git,对吗?太糟糕了,我并不总是在Linux下使用该仓库,否则,fuse-zip将是一个非常不错的主意。
乔纳斯·海德堡

2

应用程序的预压缩文件经常会出现问题,因为他们希望zip压缩方法和文件顺序成为他们选择的方法。我相信打开的Office .odf文件存在该问题。

也就是说,如果您只是使用any-old-zip作为将内容保持在一起的方法,则您应该能够创建一些简单的别名,这些别名将在需要时解压缩并重新压缩。现在,最新的Msysgit(适用于Windows的Git)在外壳程序代码侧同时具有zip和unzip,因此您可以在别名中使用它们。

我当前正在处理的项目将zips作为主要的本地版本控制/存档,因此,我也试图获取一组可行的别名,以将这数百个zip吸入git(然后再次取出;-),同事很高兴。


3
我只是对Word 2010进行了一些测试-似乎可以忍受(deflate使用不同的字号,deflate64并且更改7zip生成的zip文件中的文件顺序都不会使Word失效)。关于使用别名,我希望避免任何额外的手动步骤...目前,我的大部分提交都通过TortoiseGit进行。
乔纳斯·海德堡
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.