Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Git 为什么将同一内容压缩两次会得到两个具有不同SHA1的文件?_Git_Ant_Zip_Gzip_Sha - Fatal编程技术网

Git 为什么将同一内容压缩两次会得到两个具有不同SHA1的文件?

Git 为什么将同一内容压缩两次会得到两个具有不同SHA1的文件?,git,ant,zip,gzip,sha,Git,Ant,Zip,Gzip,Sha,我在git和zip文件方面遇到了一个奇怪的问题。我的构建脚本将一堆文档html页面压缩成docs.zip文件,然后将该文件签入git 我遇到的问题是,每次我重新运行构建脚本并获得一个新的zip文件时,新的zip文件的SHA1都与上次运行的不同。我的构建脚本正在调用ant zip任务。然而,如果我将同一个目录压缩两次,从MacOSXshell手动调用MacOSXzip会给我一个不同的sha1 运行1: zip foo.zip * openssl sha1 foo.zip rm foo.zip

我在git和zip文件方面遇到了一个奇怪的问题。我的构建脚本将一堆文档html页面压缩成docs.zip文件,然后将该文件签入git

我遇到的问题是,每次我重新运行构建脚本并获得一个新的zip文件时,新的zip文件的SHA1都与上次运行的不同。我的构建脚本正在调用ant zip任务。然而,如果我将同一个目录压缩两次,从MacOSXshell手动调用MacOSXzip会给我一个不同的sha1

运行1:

zip foo.zip *
openssl sha1 foo.zip 
rm foo.zip 
运行2:

zip foo.zip *
openssl sha1 foo.zip
运行1和运行2给出不同的SHA1,即使在运行之间内容没有更改。在这两种情况下,zip打印出的文件与正在压缩的文件完全相同。这并不表示zip文件中包含任何特定于操作系统的文件,如.DS_Store

zip算法是确定性的吗?如果在相同的内容上运行,它会产生完全相同的位吗?若否,原因为何

对于以确定性方式压缩文件,我有哪些选择?压缩文件中有数千个,我不希望这些文件有太大的变化。我知道git会将你签入的任何文件压缩,但压缩它们的动机只是为了避免它们的大量出现。

根据维基百科的说法,压缩文件似乎有标题 文件上次修改时间和文件上次修改日期,因此,如果zip是从相同的内容重新生成的,那么签入git的任何zip文件在git看来都将发生更改。而且似乎没有任何标志告诉它不要设置这些标题


我只是使用tar,如果运行多次,它似乎会为相同的输入生成相同的字节

默认情况下,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的内容,您每次都会看到不同的散列。

我成功地使用
-X
--无额外的
)标志创建了具有相同SHA1的文件

我创建了一个文件夹和几个要压缩的文件来测试它,正如预期的那样,每次都会得到不同的SHA1哈希:

$ mkdir stuff
$ echo "Stuff 1" > stuff/stuff1.txt
$ echo "Stuff 2" > stuff/stuff2.txt
$ zip -r stuff.zip stuff/
  adding: stuff/ (stored 0%)
  adding: stuff/stuff1.txt (stored 0%)
  adding: stuff/stuff2.txt (stored 0%)

$ shasum stuff.zip
1c8be43ac859bb57603be1243da14022710d22bd  stuff.zip

$ shasum stuff.zip
1c8be43ac859bb57603be1243da14022710d22bd  stuff.zip

$ zip -r stuff.zip stuff/
updating: stuff/ (stored 0%)
updating: stuff/stuff1.txt (stored 0%)
updating: stuff/stuff2.txt (stored 0%)

$ shasum stuff.zip
73920362d0f7de74d87286502e03e7126fdc0a6a  stuff.zip
但是,使用
-X
在连续压缩后得到相同的哈希值:

$ zip -r -X stuff.zip stuff/
updating: stuff/ (stored 0%)
updating: stuff/stuff1.txt (stored 0%)
updating: stuff/stuff2.txt (stored 0%)

$ shasum stuff.zip
1ed228b16d1ee803f26a8b1419f2eb3bf7fcb9f5  stuff.zip

$ zip -r -X stuff.zip stuff/
updating: stuff/ (stored 0%)
updating: stuff/stuff1.txt (stored 0%)
updating: stuff/stuff2.txt (stored 0%)

$ shasum stuff.zip
1ed228b16d1ee803f26a8b1419f2eb3bf7fcb9f5  stuff.zip

我没有时间深入研究,并找出哪些额外的信息是造成差异弹出在第一种情况下,但这可能会有助于有人试图解决它。也仅在macOS 10.12.6上测试。

使用下面的脚本创建确定性zip或jar文件

#/bin/bash
用法(){
echo“用法:./createDeterministicArtifact.sh”
出口1
}
信息(){
回音“$1”
}
条状伪影(){
如果[-z${file}];则
使用
fi
如果[-f${file}-a-s${file}];则
mkdir-p${file}.tmp
解压-oq-d${file}.tmp${file}
查找${file}.tmp-follow-exec touch-a-m-t 201912010000.00{}\+
如果[“$UNAME”==“Linux”];则
查找${file}.tmp-follow-exec chattr-a{}\+
elif[“$UNAME”==CYGWIN*| |“$UNAME”==MINGW*];然后
查找${file}.tmp-follow-exec attrib-A{}\+
fi
cd${file}.tmp
zip-rq-D-X-9-A——压缩方法deflate../${file}.new。
光盘-
rm-rf${file}.tmp
info“重新创建的确定性工件:${file}.new”
其他的
信息“输入文件为空。请验证该文件并重试”
fi
}
文件=$1
条状伪影

两件事。首先,似乎zip文件本身可能包含在zip中,因为它位于同一目录中,这可能会产生不确定的结果。第二,zip可能包含不同于运行的日期和时间。zip文件未包含在新生成的zip中,我在发布问题之前检查了一下。没错,zip存档包含不同的文件信息,包括文件修改时间(对于unix-文件权限、所有者、创建时间和事件访问时间)。这是一个正确的答案,但如果您告诉用户它是做什么的,以及它如何解决问题,则会很有帮助。在gzip帮助中“-n--压缩时没有名称,默认情况下不要保存原始文件名和时间戳…”保存的原始文件名会影响哈希值。
-X
标志可能适用于同一文件的连续压缩,但不适用于具有相同名称和内容的两个文件,甚至不适用于具有修改的访问时间的同一文件。