2012-03-15 40 views
9

我遇到了git和zip文件的一个奇怪问题。我的构建脚本需要一堆文档html页面,并将它们压缩到docs.zip中,然后将该文件检入到git中。为什么两次压缩相同的内容会给出两个具有不同SHA1的文件?

我遇到的问题是,每次我重新运行构建脚本并获取一个新的zip文件时,新的zip文件都具有与上一次运行不同的SHA1。我的构建脚本正在调用ant zip任务。然而,从Mac OS X shell中手动调用macOSX zip会给我一个不同的sha1,如果我压缩两次相同的目录。

运行1:

zip foo.zip * 
openssl sha1 foo.zip 
rm foo.zip 

运行2:

zip foo.zip * 
openssl sha1 foo.zip 

运行1和RUN2给出不同的SHA1即使内容没有运行之间变化。在这两种情况下,压缩文件都会打印出完全相同的压缩文件,并不表示像.DS_Store这样的操作系统特定文件将被包含在压缩文件中。

拉链算法是确定性的吗?如果运行在相同的内容上,它会产生完全相同的位?如果不是为什么不呢?

我以确定性的方式压缩文件有什么选择?压缩文件中有成千上万个文件,我不希望这些文件有太大的改变。我知道git会压缩任何你签入的文件,但是压缩它们的动机是保持它们的质量。

+2

两件事。首先,zip文件本身似乎可能包含在zip中,因为它位于相同的目录中,这可能会导致不确定的结果。其次,zip可能包含日期和时间,这些日期和时间将与运行时间不同。 – 2012-03-15 04:52:47

+0

zip文件未包含在新生成的zip中,我在发布我的问题之前检查了该文件。 – ams 2012-03-15 04:58:26

回答

8

根据维基百科http://en.wikipedia.org/wiki/Zip_(file_format)似乎zip文件有 文件的最后修改时间标题和文件的最后修改日期,以便签入Git的任何zip文件会出现与git如果拉链是由因为同样的内容重建已经改变。而且似乎没有标志告诉它不设置这些标题。

我只是使用tar,它似乎产生相同的输入多个相同的输入字节。

+0

没错,ZIP归档文件包含不同的文件信息,包括文件修改时间(以及unix文件权限,所有者,创建时间和事件访问时间)。 – 2013-04-23 12:22:42

7

默认情况下,Gzip已保存的文件名和时间戳

%> gzip -help 2>&1 | grep -e '-n' 
-N --name   save or restore original file name and time stamp 
-n --no-name   don't save original file name or time stamp 

%> gzip -V 
Apple gzip 272 

使用-n选项:

%> tar cv foo/ | gzip -n > foo.tgz; shasum foo.tgz # sha256sum on Ubuntu 

,你会始终得到相同的哈希值。

在没有-n的情况下尝试以上操作,每次都应该看到不同的散列值。

+4

这是一个正确的答案,但如果您告诉用户它做了什么以及它如何解决问题,这将会很有帮助。从gzip帮助“-n --no-name 压缩时,默认情况下不保存原始文件名和时间戳...” 保存的原始文件名影响哈希。 – 2016-07-06 23:08:09

相关问题