Making git check the working directory for integrity

git

Does git have a built-in way* to check whether files in the working directory magically** changed***?

If so: How does one make git check the working directory for integrity?

* Figuring out which files in the working directory are tracked, hashing only them, deleting them, checking them out, again, hashing them, again, and comparing the hashes doesn't quite count as "built-in".

** Files' contents changed because of a cosmic ray hitting the HDD, a unicorn galloping over the plates, or other means which doesn't let the FS know that a change happened (like editing the character device).

*** In name, contents, or other tracked properties (like having magically become executable).


Note that this question is a weakened version of that other question. Answering this question (the one you're currently reading) is easier. I will link to this question in the other question if this question gets solved and point out the parts of the other question which haven't been solved by the answers below this question.

It has been asked what the difference between git status and what I'm asking for is. git status only notices changes if the FS tells it that changes happened. If files got corrupted magically, the FS doesn't know, therefore, git status won't indicate a change. git diff, git add --all, etc. won't either, of course.


In response to the proposal of using git fsck: It doesn't work.

What I did:

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

At this point, I opened /tmp/con in my favorite hex editor, searched for the word "contents", and swapped the "s" in the end out for a "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

I has been proposed to touch all files in the working directory. Changing their accessed date wouldn't be much of a problem but that doesn't make git recheck the file. Changing their modified date actually does make git check those files again, however, it also causes other trouble: Backup applications back the file up, again. With big repositories, this can be a problem.

Best Answer

I was reading an answer to another question, about how to make git acknowledge your new line-ending preferences on github, and it included this gem:

  1. Remove the index and force Git to rescan the working directory.

    rm .git/index

  2. Rewrite the Git index to pick up all the new line endings.

    git reset

  3. Show the rewritten, normalized files.

    git status

It suggests saving your current state in case you have anything else you care about, which might be relevant.

Especially since the git reset step will rewrite the file.

Related Question