3

Имеется ли в git встроенный способ * проверки того, что файлы в рабочем каталоге волшебным образом ** изменились ***?

Если так: Как заставить git проверить рабочий каталог на целостность?

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

** Содержимое файлов изменилось из-за космического луча, падающего на жесткий диск, единорога, скачущего по тарелкам, или других средств, которые не позволяют FS узнать, что произошло изменение (например, редактирование устройства символов).

*** В имени, содержимом или других отслеживаемых свойствах (например, магическим образом становится исполняемым).


Обратите внимание, что этот вопрос является ослабленной версией этого другого вопроса. Ответить на этот вопрос (тот, который вы сейчас читаете) проще. Я свяжусь с этим вопросом в другом вопросе, если этот вопрос будет решен, и укажу части другого вопроса, которые не были решены ответами ниже этого вопроса.

Был задан вопрос, в чем разница между git status и тем, что я прошу. git status только замечает изменения, если FS сообщает, что изменения произошли. Если файлы были повреждены магическим образом, FS не знает, поэтому git status не будет указывать на изменение. git diff , git add --all и т. д. тоже не будут, конечно.


В ответ на предложение использовать git fsck: он не работает.

Что я сделал:

christoph@christoph-laptop-16-04-2:/t$ dd if=/dev/zero bs=1M count=30 of=/tmp/con
30+0 records in
30+0 records out
31457280 bytes (31 MB, 30 MiB) copied, 0.0143967 s, 2.2 GB/s
christoph@christoph-laptop-16-04-2:/t$ mkfs.ext4 /tmp/con
mke2fs 1.42.13 (17-May-2015)
Discarding device blocks: done                            
Creating filesystem with 30720 1k blocks and 7680 inodes
Filesystem UUID: 9865efe8-fb30-42ab-ace7-a8f88330bdfd
Superblock backups stored on blocks: 
    8193, 24577

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done

christoph@christoph-laptop-16-04-2:/t$ sudo mount -t ext4 -o loop /tmp/con /mnt
[sudo] password for christoph: 
christoph@christoph-laptop-16-04-2:/t$ cd /mnt
christoph@christoph-laptop-16-04-2:/mnt$ sudo chown christoph .
christoph@christoph-laptop-16-04-2:/mnt$ git init
Initialized empty Git repository in /mnt/.git/
christoph@christoph-laptop-16-04-2:/mnt$ echo "some contents" > file
christoph@christoph-laptop-16-04-2:/mnt$ git add file 
christoph@christoph-laptop-16-04-2:/mnt$ git commit -m "a"
[master (root-commit) d29fbd5] a
 1 file changed, 1 insertion(+)
 create mode 100644 file
christoph@christoph-laptop-16-04-2:/mnt$ git status
On branch master
nothing to commit, working directory clean
christoph@christoph-laptop-16-04-2:/mnt$ cd ~
christoph@christoph-laptop-16-04-2:~$ sudo umount /mnt

В этот момент я открыл /tmp/con в моем любимом шестнадцатеричном редакторе, искал слово "содержимое" и поменял местами "s" на "z".

christoph@christoph-laptop-16-04-2:~$ sudo mount -t ext4 -o loop /tmp/con /mnt
christoph@christoph-laptop-16-04-2:~$ cd /mnt
christoph@christoph-laptop-16-04-2:/mnt$ git status
On branch master
nothing to commit, working directory clean
christoph@christoph-laptop-16-04-2:/mnt$ cat file 
some contentz
christoph@christoph-laptop-16-04-2:/mnt$ git fsck
Checking object directories: 100% (256/256), done.
christoph@christoph-laptop-16-04-2:/mnt$ git status
On branch master
nothing to commit, working directory clean
christoph@christoph-laptop-16-04-2:/mnt$ cat file
some contentz

Мне было предложено перебрать все файлы в рабочем каталоге. Изменение даты обращения к ним не будет большой проблемой, но это не заставит git перепроверить файл. Изменение даты их изменения на самом деле заставляет git снова проверять эти файлы, однако это также вызывает другие проблемы: резервные копии приложений снова копируют файл. С большими репозиториями это может быть проблемой.

2 ответа2

0

Я читал ответ на другой вопрос о том, как заставить git распознавать ваши новые настройки окончания строки в github, и он включал этот гем:

  1. Удалите индекс и заставьте Git выполнить повторное сканирование рабочего каталога.

    rm .git/index

  2. Перепишите индекс Git, чтобы получить все новые окончания строк.

    git reset

  3. Покажите переписанные, нормализованные файлы.

    git status

Он предлагает сохранить ваше текущее состояние на случай, если у вас есть что-то еще, что вас волнует, что может иметь значение.

Тем более что шаг git reset перезапишет файл.

0

Этот ответ на SO говорит, что:

Git изо всех сил пытается убедить только из значения lstat(), что рабочее дерево соответствует индексу, потому что откат к содержимому файла очень дорогой.

Другими словами, сравнение побайтовых файлов заняло бы довольно много времени, поэтому git пытается оптимизировать его, сначала сравнивая результаты функции lstat . Это включает в себя размер файла и время модификации. Если они не изменены, git предполагает, что файл не был изменен. Как вы доказали, это не надежный метод, но он работает для случаев, для которых предназначен git.

Изменение любого из значений, возвращаемых lstat , заставит git перепроверить файлы для модификации:

$ touch file
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   file

no changes added to commit (use "git add" and/or "git commit -a")

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .