让 git 检查工作目录的完整性

让 git 检查工作目录的完整性

git 是否有内置方法*来检查工作目录中的文件是否神奇地**发生了变化***?

如果是这样:如何让 git 检查工作目录的完整性?

* 确定工作目录中哪些文件被跟踪、仅对它们进行哈希处理、删除它们、再次检出它们、再次对它们进行哈希处理并比较哈希值,这并不完全算作“内置”。

** 文件的内容因为宇宙射线撞击 HDD、独角兽在盘子上奔跑或其他不让 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我最喜欢的十六进制编辑器,搜索单词“contents”,并将结尾的“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 再次检查这些文件,但是,这还会引起其他麻烦:备份应用程序会再次备份文件。对于大型存储库,这可能是一个问题。

答案1

我正在阅读另一个问题的答案,关于如何让 git 确认你的新行尾偏好在 github 上,其中包括这颗宝石:

  1. 删除索引并强制 Git 重新扫描工作目录。

    rm .git/index

  2. 重写 Git 索引以获取所有新的行尾。

    git reset

  3. 显示重写的、规范化的文件。

    git status

它建议保存您当前的状态,以防您还有其他关心的、可能相关的信息。

特别是因为 git reset 步骤将重写文件。

答案2

这个答案说:

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")

相关内容