Как восстановить поврежденные файлы PNG из-за неправильных .gitattributes? - PullRequest
1 голос
/ 25 марта 2019

Я добавил, зафиксировал и поместил несколько файлов PNG в репозиторий git, но, к сожалению, у меня был неподходящий файл .gitattributes, такой как:

* text
# no settings for PNG files

Файлы PNG были обработаны git как текстовые файлы. Теперь я не могу их больше открыть, и я также потерял их оригинальную копию. Есть ли способ их восстановить? Спасибо!


Обновление : .gitattributes уже был в репо, когда были добавлены файлы PNG. Это означает, что я не могу найти хорошее состояние для файлов PNG в истории фиксации. И все коммиты были сделаны на Windows.

Ответы [ 2 ]

3 голосов
/ 26 марта 2019

Давайте рассмотрим сценарий, в котором у вас есть 2 коммита:

  • В первом случае все файлы PNG обрабатываются как двоичные, файлы являются звуковыми.
  • Второй коммит включает *Файл 1006 * и все файлы PNG будут повреждены, поскольку они рассматриваются как текстовые файлы.

Вот вывод git log:

commit d075d282795362e03318d93c36406822facc015c (HEAD -> master)
Author: John Doe <john.doe@users.noreply.github.com>
Date:   Tue Mar 26 17:12:16 2019 +0100

    Bad state
    Gitattributed file added, PNG files are treated as text, they are now corrupted

commit fcaa5a87eb816ddafbd256e83ea4be004a87a6e8
Author: John Doe <john.doe@users.noreply.github.com>
Date:   Tue Mar 26 17:11:36 2019 +0100

    Good state
    PNG Files are treated as binary, they are not corrupted yet

Сначала верните все файлы PNG в исходное состояние:

git reset fcaa5a87eb816ddafbd256e83ea4be004a87a6e8 -- *.png

Затем зафиксируйте изменения без добавления файла:

git commit -m 'Fix PNG files'

Отмена всех изменений из рабочего каталога:

git checkout '*.png'

Окончательно удалитеошибочный .gitattributes введите или замените его на:

*.png binary

Вы также можете использовать шаблон gitattributes , включая многие другие типы файлов.


Обновление:

Если нет «хорошего» состояния, в котором изображения были неповрежденными, вы можете попытаться исправить проблему, манипулируя файлами.Вам необходимо добавить недостающие символы новой строки.Вы не знаете правильные позиции, так как git удалил их все.По моему опыту, если вы добавите только один возврат каретки в конце первой строки, это исправит большинство небольших файлов PNG.Я не знаю почему, и нет никакой гарантии, но вы все равно можете попробовать:

Сначала удалите все файлы PNG:

rm -f *.png

Затем объявите файлы PNG как двоичныев .gitattributes:

*.png binary

Восстановить файлы:

git checkout '*.png'

Добавить возврат каретки в конце первой строки:

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

2 голосов
/ 30 марта 2019

TL; DR

Для небольших файлов это легко, для файлов в диапазоне 60-200 КБ это все еще возможно, для больших файлов - безнадежно.

Ноль или одна случайная новая строка повреждены

Легко движется.

Этот сценарий грубой силы bash, построенный на однострочном Perl, предоставленном @Denizв своем ответе работал над файлом, который потерял всего одну случайную новую строку после того, что за магическим числом:

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

Файл был размером 97 КБ, и это заняло около 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 КБ, у вас может быть некоторая надежда на этоподход, если вам повезло, что не более 2 случайных новых строк были повреждены, но от 3 раслучайные переводы строк безнадежны.Помните, что вы ожидаете в среднем один случайный поврежденный перевод строки на 64 КБ.Поэтому, конечно, если вам не повезло, даже в меньшем файле могло быть больше CRLF.

Три или более случайных символа новой строки повреждены

Просто забудьте об этом!

У меня есть файл размером 464 КБ, с которым я играю, и я знаю, что 3 случайных символа новой строки были повреждены (случайно меньше, чем ожидалось, я думаю, мне повезло), кроме одного настрока 1 (в магическом числе), и моя оценка состоит в том, что потребуется 4 года, чтобы найти правильную комбинацию с подходом грубой силы.Я не в бизнесе!

В этом случае я работаю с 3-х глубокой версией этой грубой силовой петли.Я собираюсь дать ему поработать несколько дней ради удовольствия, но я не ожидаю, что он что-то найдет, так как я не хочу позволить ему работать в течение 4 лет ...

Фон

Приведенные выше сценарии основаны на следующих предположениях:

Заголовок

Файлы PNG имеют магическое число - 8-заголовок байта - который содержит две новые строки, одну в формате CRLF в стиле Dos и одну LF в стиле Unix.Они существуют именно для того, чтобы выявлять искажения в результате перевода строки.Поэтому исправление файла потребует исправления магического числа, например, используя решение, предоставленное @Deniz в его ответе.

Ссылка: https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header

Тело

Тело файла PNG сжато, и поэтому мы можем ожидать высокого энтропийного случайного распределения байтов и пар байтов в нем, например, равномерное распределение.(Это то, к чему стремятся алгоритмы сжатия, в конце концов!) Таким образом, мы можем ожидать в среднем 1 символ новой строки на 256 байтов, и в среднем 1 из 256 из них будет CRLF.Таким образом, у нас есть в среднем один LF для преобразования обратно в CRLF на 64 КБ файла PNG.

pngcheck

Программа pngcheck (среди прочих яобязательно) может использоваться для проверки действительности файла PNG, включая его магический номер и контрольную сумму, хранящуюся в файле.Таким образом, мы можем использовать, чтобы узнать, когда мы обнаружили, какие LF были изначально CRLF.

«Правильное» решение

Хорошее решение этой проблемы будет использовать дальнейшее знаниеформат данных и принять обоснованное решение для каждой новой строки.Например, можно проанализировать два потока распакованных данных, полученных в результате рассмотрения еще нескольких десятков байтов после каждой новой строки, предполагая, что новая строка изначально была LF или CRLF соответственно.При глубоком знании формата данных или, возможно, некоторого машинного обучения, это должно быть возможно ...

Решение для перебора

Не имея глубокого понимания формата файла PNG, можно восстановить небольшие файлы с помощью грубой силы, попробовав все комбинации преобразования до двух случайно поврежденных строк новой строки обратно в CRLF.Однако вычислительные затраты являются экспоненциальными в количестве CRLF в исходном файле, поэтому обобщение подхода за пределы двух искаженных случайных строк новой строки не имеет смысла.

...