如何恢复由于不正确的.git属性而损坏的PNG文件?

如何恢复由于不正确的.git属性而损坏的PNG文件?,git,png,gitattributes,Git,Png,Gitattributes,我在我的git repo中添加了几个PNG文件,但不幸的是,我有一个不正确的.gittributes文件,如下所示: * text # no settings for PNG files git将PNG文件视为文本文件。现在我再也无法打开它们了,我也丢失了它们的原件。有没有办法找回它们?谢谢 更新:添加PNG文件时,.gittributes已在repo中。这意味着我在提交历史记录中找不到PNG文件的良好状态。所有提交都是在Windows上进行的。让我们看一个场景,其中有两个提交: 在第一种方法

我在我的git repo中添加了几个PNG文件,但不幸的是,我有一个不正确的.gittributes文件,如下所示:

* text
# no settings for PNG files
git将PNG文件视为文本文件。现在我再也无法打开它们了,我也丢失了它们的原件。有没有办法找回它们?谢谢


更新:添加PNG文件时,.gittributes已在repo中。这意味着我在提交历史记录中找不到PNG文件的良好状态。所有提交都是在Windows上进行的。

让我们看一个场景,其中有两个提交:

在第一种方法中,所有PNG文件都作为二进制文件处理,这些文件都是声音文件。 第二次提交包括.gittributes文件,所有PNG文件都会损坏,因为它们被视为文本文件。 以下是git日志输出:

首先将所有PNG文件重置为其初始状态:

git重置FCAA5A87EB816DDAFBD256E83EA4BE04A87A6E8-*.png

然后提交更改而不添加任何文件:

git提交-m“修复PNG文件”

放弃工作目录中的所有更改:

git签出“*.png”

最后删除错误的.gittributes条目或将其替换为:

*.png二进制文件

您还可以使用包含许多其他文件类型的

更新: 如果没有图像完好无损的“良好”状态,您可以尝试通过操作文件来解决问题。您需要添加缺少的换行符。你不知道正确的位置,因为git已经把它们全部移除了。根据我的经验,如果在第一行末尾添加一个回车符,它将修复大多数小PNG文件。我不知道为什么,也不能保证,但您仍然可以尝试:

首先删除所有PNG文件:

rm-f*.png

然后在.gittributes中将PNG文件声明为二进制文件:

*.png二进制文件

还原文件:

git签出“*.png”

在第一行末尾添加回车符:


perl-i-p-e的/$/$1\r/if$.==1;' *.png

让我们看一个场景,其中有两个提交:

在第一种方法中,所有PNG文件都作为二进制文件处理,这些文件都是声音文件。 第二次提交包括.gittributes文件,所有PNG文件都会损坏,因为它们被视为文本文件。 以下是git日志输出:

首先将所有PNG文件重置为其初始状态:

git重置FCAA5A87EB816DDAFBD256E83EA4BE04A87A6E8-*.png

然后提交更改而不添加任何文件:

git提交-m“修复PNG文件”

放弃工作目录中的所有更改:

git签出“*.png”

最后删除错误的.gittributes条目或将其替换为:

*.png二进制文件

您还可以使用包含许多其他文件类型的

更新: 如果没有图像完好无损的“良好”状态,您可以尝试通过操作文件来解决问题。您需要添加缺少的换行符。你不知道正确的位置,因为git已经把它们全部移除了。根据我的经验,如果在第一行末尾添加一个回车符,它将修复大多数小PNG文件。我不知道为什么,也不能保证,但您仍然可以尝试:

首先删除所有PNG文件:

rm-f*.png

然后在.gittributes中将PNG文件声明为二进制文件:

*.png二进制文件

还原文件:

git签出“*.png”

在第一行末尾添加回车符:

perl-i-p-e的/$/$1\r/if$.==1;' *.巴布亚新几内亚;博士

对于小文件来说,这很容易,对于60-200KB范围内的文件,这应该仍然是可行的,对于较大的文件,这是没有希望的

零或一个随机换行符损坏

容易相处

这个蛮力bash脚本构建在@Deniz在其回答中提供的Perl one liner上,它处理的文件在神奇数字中的一行之后只丢失了一个随机换行:

lines=`wc -l < image.corrupted.png`
for x in `seq 1 $((lines+1))`; do 
   echo -n $x ''
   perl -pe 's/$/$1\r/ if ($. == 1 || $. =='$x')' < image.corrupted.png > image.fixed.png
   if pngcheck image.fixed.png; then
      echo Valid file substituting newline numbers 1 and $x
      break
   fi
done
该文件的大小为97KB,耗时约11秒

两个随机换行符损坏

耐心点

这应该适用于缺少两个随机换行符加上初始换行符的情况:

lines=`wc -l < image.corrupted.png`
foundit=
for x in `seq 3 $((lines+1))`; do 
   date
   echo $x
   time for y in `seq 3 $((lines+1))`; do
      echo -n $y ''
      perl -pe 's/$/$1\r/ if ($. == 1 || $. =='$x' || $. =='$y')' < image.corrupted.png > image.fixed.png
      if pngcheck image.fixed.png; then
         echo Valid file substituting newline numbers 1, $x and $y
         foundit=1
         break
      fi
   done
   if [[ $foundit ]]; then
      break
   fi
done
完成内部循环的一次迭代需要2分钟,找到固定图像需要一天半的时间

如果您的文件小于200 KB,您可能会对这种方法有一些希望,如果您足够幸运,没有超过2个随机换行符被破坏,但从3个随机换行符开始,这是没有希望的。请记住,平均每64 KB有一个随机损坏的换行符。因此,如果您运气不好,即使是较小的文件也可能有更多的CRLF

三个或更多随机换行符已损坏

算了吧

我有一个464KB的文件,我知道3个随机换行符被破坏的几率比预期的要少,我想我很幸运,除了魔法数字中第1行的那个,我估计需要4年时间才能找到与暴力方法的正确组合。我不是做生意的

在这种情况下,我正在跑步 一个3深版本的蛮力循环。为了好玩,我打算让它运行几天,但我不希望它找到任何东西,因为我不愿意让它运行4年

背景

上述脚本基于以下假设:

标题

PNG文件有一个神奇的数字——一个8字节的头——它包含两个换行符,一个是Dos风格的CRLF格式,另一个是Unix风格的LF格式。它们的存在正是为了检测换行符转换中的损坏。因此,修复文件需要修复幻数,例如,使用@Deniz在其答案中提供的解决方案

参考:

身体

PNG文件的主体是压缩的,因此我们可以预期其中字节和字节对的高熵随机分布,例如,均匀分布。毕竟,这就是压缩算法努力实现的目标!因此,我们可以预期平均每256个字节有1个换行符,其中256个字节中平均有1个是CRLF。因此,平均每64KB PNG文件中有一个LF要转换回CRLF

pngcheck

我确信pngcheck等程序可以用来验证PNG文件的有效性,包括文件中存储的幻数和校验和。所以我们可以用来知道什么时候我们发现哪些LF最初是CRLF

正确的解决方案

这个问题的一个好的解决方案是利用对数据格式的进一步了解,并为每条换行做出明智的决定。例如,假设换行符最初分别为LF或CRLF,则可以分析由于在每个换行符之后考虑几十个字节而产生的两个解压缩数据流。有了对数据格式的深入了解,或者一些机器学习,这应该是可能的

蛮力解决方案

由于缺乏对PNG文件格式的深入了解,人们可以通过暴力恢复小文件,尝试将多达两个随机损坏的换行符转换回CRLF的所有组合。然而,计算成本与原始文件中CRLF的数量成指数关系,因此将该方法推广到两个损坏的随机换行之外是毫无意义的;博士

对于小文件来说,这很容易,对于60-200KB范围内的文件,这应该仍然是可行的,对于较大的文件,这是没有希望的

零或一个随机换行符损坏

容易相处

这个蛮力bash脚本构建在@Deniz在其回答中提供的Perl one liner上,它处理的文件在神奇数字中的一行之后只丢失了一个随机换行:

lines=`wc -l < image.corrupted.png`
for x in `seq 1 $((lines+1))`; do 
   echo -n $x ''
   perl -pe 's/$/$1\r/ if ($. == 1 || $. =='$x')' < image.corrupted.png > image.fixed.png
   if pngcheck image.fixed.png; then
      echo Valid file substituting newline numbers 1 and $x
      break
   fi
done
该文件的大小为97KB,耗时约11秒

两个随机换行符损坏

耐心点

这应该适用于缺少两个随机换行符加上初始换行符的情况:

lines=`wc -l < image.corrupted.png`
foundit=
for x in `seq 3 $((lines+1))`; do 
   date
   echo $x
   time for y in `seq 3 $((lines+1))`; do
      echo -n $y ''
      perl -pe 's/$/$1\r/ if ($. == 1 || $. =='$x' || $. =='$y')' < image.corrupted.png > image.fixed.png
      if pngcheck image.fixed.png; then
         echo Valid file substituting newline numbers 1, $x and $y
         foundit=1
         break
      fi
   done
   if [[ $foundit ]]; then
      break
   fi
done
完成内部循环的一次迭代需要2分钟,找到固定图像需要一天半的时间

如果您的文件小于200 KB,您可能会对这种方法有一些希望,如果您足够幸运,没有超过2个随机换行符被破坏,但从3个随机换行符开始,这是没有希望的。请记住,平均每64 KB有一个随机损坏的换行符。因此,如果您运气不好,即使是较小的文件也可能有更多的CRLF

三个或更多随机换行符已损坏

算了吧

我有一个464KB的文件,我知道3个随机换行符被破坏的几率比预期的要少,我想我很幸运,除了魔法数字中第1行的那个,我估计需要4年时间才能找到与暴力方法的正确组合。我不是做生意的

在这种情况下,我运行的是一个3深版本的蛮力循环。为了好玩,我打算让它运行几天,但我不希望它找到任何东西,因为我不愿意让它运行4年

背景

上述脚本基于以下假设:

标题

PNG文件有一个神奇的数字——一个8字节的头——它包含两个换行符,一个是Dos风格的CRLF格式,另一个是Unix风格的LF格式。它们的存在正是为了检测换行符转换中的损坏。因此,修复文件需要修复幻数,例如,使用@Deniz在其答案中提供的解决方案

参考:

身体

PNG文件的主体是压缩的,因此我们可以预期其中字节和字节对的高熵随机分布,例如,均匀分布。毕竟,这就是压缩算法努力实现的目标!因此,我们可以预期平均每256个字节有1个换行符,其中256个字节中平均有1个是CRLF。因此,平均每64KB PNG文件中有一个LF要转换回CRLF

pngcheck

我确信pngcheck等程序可以用来验证PNG文件的有效性,包括文件中存储的幻数和校验和。所以我们可以用来知道什么时候我们发现哪些LF最初是CRLF

正确的解决方案

A 解决这个问题的好办法是利用对数据格式的进一步了解,并为每条换行做出明智的决定。例如,假设换行符最初分别为LF或CRLF,则可以分析由于在每个换行符之后考虑几十个字节而产生的两个解压缩数据流。有了对数据格式的深入了解,或者一些机器学习,这应该是可能的

蛮力解决方案



由于缺乏对PNG文件格式的深入了解,人们可以通过暴力恢复小文件,尝试将多达两个随机损坏的换行符转换回CRLF的所有组合。然而,计算成本与原始文件中CRLF的数量成指数关系,因此将该方法推广到两个损坏的随机换行之外是毫无意义的。

这是一个行尾字符的问题,因此,您可以尝试用CRLF替换所有出现的LF char,但不保证成功。我想,如果您出现这个问题,是因为您在Windows上使用git,我认为这是不可能的,因为您需要以某种方式检测哪些LF最初是CRLF,哪些不是。我不知道如何在压缩的二进制流中做到这一点。我认为可能性只有几个LF,而最初的CRLF假设LF之前的字符在压缩流中的分布非常接近均匀,因此修复工具可以尝试各种可能的方法来更改一个LF,然后更改两个LF的每个组合,等等,但显然这将非常昂贵,和手动,除非有自动检测有效固定文件的方法。您是否尝试将文本eol=crlf放入.gittributes中?@DenizToprak尝试过,但仍然无法打开。也许是因为我在Mac电脑上工作。我现在没有访问Windows的权限。@joanis恐怕你是对的。PNG文件相对较大,大于1MB。将有太多的LFs需要尝试。这是一个行尾字符的问题,因此您可以尝试用CRLF替换所有出现的LF字符,但不保证成功。我想,如果您有这个问题,是因为您在Windows上使用git,我认为这是不可能做到的,因为你需要以某种方式检测哪些LF最初是CRLF,哪些不是。我不知道如何在压缩的二进制流中做到这一点。我认为可能性只有几个LF,而最初的CRLF假设LF之前的字符在压缩流中的分布非常接近均匀,因此修复工具可以尝试各种可能的方法来更改一个LF,然后更改两个LF的每个组合,等等,但显然这将非常昂贵,和手动,除非有自动检测有效固定文件的方法。您是否尝试将文本eol=crlf放入.gittributes中?@DenizToprak尝试过,但仍然无法打开。也许是因为我在Mac电脑上工作。我现在没有访问Windows的权限。@joanis恐怕你是对的。PNG文件相对较大,大于1MB。要尝试的LFs太多了。谢谢你的帮助。但这不是我的设想。在我的例子中,添加PNG文件时,bad.gittributes文件已经存在。这意味着git提交历史记录中没有PNG文件的良好状态。这仍然可以解决吗?我发现这只适用于小PNG文件,其中0x0a0d模式只出现一次。如果存在多个0x0a0d模式实例,则处理后的PNG文件可能无法正确打开,也可能根本无法打开。即使是在一个大的.PNG文件中,该模式也不应该经常出现。您是否尝试过在1到10或20之间循环,并更改$。==每个数字1个,看看是否有效?我怀疑在大多数情况下,您试图恢复的原始文件中只有一个0x0a0d实例。毕竟,假设压缩试图实现统一的分布,那么每64kB应该只有一个该模式的实例。好的,这不是一个大文件,也许我对这种方法过于乐观…@joanis,正如你之前评论的那样,我必须弄清楚哪些LFs最初是CRLFs。尽管0x0a0d模式在原始文件中不太常见,但我不知道这一点。我所拥有的只是损坏的文件,每个0x0a字节都是可疑的。只是读取了一些.png格式。幻数同时具有Unix和DOS行端,通过行端转换精确地检测损坏。您的解决方案修复了魔法数字,从而禁用了早期损坏检测。任何在损坏之前不包含0x0a0d的文件都将由您的解决方案修复,这解释了为什么它适用于大多数小png文件。谢谢你的帮助。但这不是我的设想。在我的例子中,添加PNG文件时,bad.gittributes文件已经存在。这意味着git提交历史记录中没有PNG文件的良好状态。这仍然可以解决吗?我发现这只适用于小PNG文件,其中0x0a0d模式只出现一次。如果存在多个0x0a0d模式实例,则处理后的PNG fil
e要么无法正确打开,要么根本无法打开。即使在一个大的.png文件中,这种模式也不应该经常出现。您是否尝试过在1到10或20之间循环,并更改$。==每个数字1个,看看是否有效?我怀疑在大多数情况下,您试图恢复的原始文件中只有一个0x0a0d实例。毕竟,假设压缩试图实现统一的分布,那么每64kB应该只有一个该模式的实例。好的,这不是一个大文件,也许我对这种方法过于乐观…@joanis,正如你之前评论的那样,我必须弄清楚哪些LFs最初是CRLFs。尽管0x0a0d模式在原始文件中不太常见,但我不知道这一点。我所拥有的只是损坏的文件,每个0x0a字节都是可疑的。只是读取了一些.png格式。幻数同时具有Unix和DOS行端,通过行端转换精确地检测损坏。您的解决方案修复了魔法数字,从而禁用了早期损坏检测。任何在损坏之前不包含0x0a0d的文件都将由您的解决方案修复,这解释了为什么它适用于大多数小png文件。裁判:跑得好。Joanis2023下一个挑战:使用机器学习来决定每条换行的是或否,而不必以这种蛮力的方式处理整个文件,或者在读取几个字节后使用png规范来决定每条是/否决定的有效性。我想这是可以做到的,但现在我肯定不是在努力@Romanvaleri很好的散列标签:根据一夜之间的进展情况,我可能需要将其更新为joanis2027。。。加油@本,不客气,我很抱歉。无论如何,处理这个问题都很有趣。你从来没有说过你的文件有多大,但我假设比我的测试用例大?@joanis这些文件大于1MB。实际上还有一些JPG文件需要解救。但没关系,跑得好。Joanis2023下一个挑战:使用机器学习来决定每条换行的是或否,而不必以这种蛮力的方式处理整个文件,或者在读取几个字节后使用png规范来决定每条是/否决定的有效性。我想这是可以做到的,但现在我肯定不是在努力@Romanvaleri很好的散列标签:根据一夜之间的进展情况,我可能需要将其更新为joanis2027。。。加油@本,不客气,我很抱歉。无论如何,处理这个问题都很有趣。你从来没有说过你的文件有多大,但我假设比我的测试用例大?@joanis这些文件大于1MB。实际上还有一些JPG文件需要解救。但没关系。。。