简体   繁体   English

git如何在Windows上检测修改的文件?

[英]How does git detect modified files on Windows?

(This is not a duplicate of How does git detect that a file has been modified? because I'm asking about Windows, the referenced QA mentions stat and lstat , which do not apply to Windows). (这不是git如何检测到文件已被修改的副本因为我在询问Windows,引用的质量检查提到statlstat ,不适用于Windows)。

With traditional systems like SVN and TFS, the "state database" needs to be explicitly and manually informed of any changes to files in your local workspace: files are read-only by default so you don't accidentally make a change without explicitly informing your SVN/TFS client first. 对于像SVN和TFS这样的传统系统,需要在本地工作区中明确地手动通知“状态数据库”,以了解对文件的任何更改:默认情况下文件是只读的,因此在不显式通知您的情况下,您不会偶然进行更改SVN / TFS客户端优先。 Fortunately IDE integration means that operations that result in the addition, modification, deletion and renaming (ie "checking-out") of files can be automatically passed on to the client. 幸运的是,IDE集成意味着导致文件添加,修改,删除和重命名(即“签出”)的操作可以自动传递给客户端。 It also means that you would need something like TortoiseSVN to work with files in Windows Explorer, lest your changes be ignored - and that you should regularly run an often lengthy Server-to-Local comparison scan to detect any changes. 这也意味着您需要像TortoiseSVN这样的东西才能在Windows资源管理器中处理文件,以免您的更改被忽略-并且您应该定期运行通常很长时间的“服务器到本地”比较扫描以检测任何更改。

But Git doesn't have this problem - on my Windows machine I can have a gigabyte-sized repo with hundreds of thousands of files, many levels deep, and yet if I make a 1 byte change to a file nested very deeply, I can see that Git knows after running git status . 但是Git并没有这个问题-在我的Windows机器上,我可以有一个千兆字节的存储库,其中包含成千上万个文件,深度很深,但是如果我对嵌套的文件进行1字节的更改,我可以看到Git在运行git status之后就知道了。 This is the strange part - because git does not use any daemon processes or background tasks - running git status also does not involve any significant IO activity that I can see, I get the results back immediately, it does not thrash my disk searching for the change I made. 这是很奇怪的部分-因为git不使用任何守护进程或后台任务-运行git status也不涉及任何我可以看到的重要IO活动,我可以立即返回结果,它不会影响我的磁盘搜索我做了改变。

Additionally, Git GUI tools, such as the Git integration with Visual Studio 2015 also have some degree of magic in them - I can make a change in Notepad or another program, and VS' Git Changes window picks it up immediately. 此外,Git GUI工具(例如与Visual Studio 2015集成的Git)也具有一定的魔力-我可以在记事本或其他程序中进行更改,而VS'Git Changes窗口会立即将其选中。 VS could simply be using ReadDirectoryChanges ( FileSystemWatcher ) - but when I look at the devenv process in Process Explorer I don't see any corresponding handles, but that also doesn't explain how git status sees the changes. VS可能只是使用ReadDirectoryChangesFileSystemWatcher )-但是当我在Process Explorer中查看devenv进程时,我看不到任何对应的句柄,但这也无法解释git status如何看到这些变化。

Git runs a Windows equivalent of the POSIX-y lstat(2) call on each file recorded in the index to have the first stab at figuring out whether the file is modified or not. Git在索引中记录的每个文件上运行Windows等效于POSIX-y lstat(2)调用的Windows,以首先确定文件是否被修改。 It compares the modification time and size taken from that information with the values recorded for that file in the index. 它将从该信息中获取的修改时间和大小与索引中为该文件记录的值进行比较。

This operation is notoriously slow on NTFS (and network-mapped drives) so since some time Git for Windows gained a special tweak controlled with the core.fscache configuration option which became enabled by default some 2 or 3 GfW releases ago. 众所周知,此操作在NTFS(和网络映射的驱动器)上很慢,因此自一段时间以来,Windows的Git获得了由core.fscache配置选项控制的特殊调整,该选项在大约2或3个GfW版本之前默认启用。 I don't know the exact details but it tries to minimize the number of times Git needs to lstat(2) your files. 我不知道确切的详细信息,但是它试图最小化Git进行lstat(2)文件所需的次数。

IIUC, the mechanism enabled by core.fscache is not making use of filesystem watching Win32 API as Git runs no daemons/services on your system; IIUC,由core.fscache启用的机制没有使用监视Win32 API的文件系统,因为Git在您的系统上没有运行守护程序/服务; so it merely optimizes the way Git asks the filesystem layer about the stat info of the tracked files. 因此,它仅优化了Git向文件系统层询问所跟踪文件的统计信息的方式。

As Briana Swift and kostix point out - it is scanning your disk. 正如Briana Swift和kostix指出的-它正在扫描您的磁盘。 However, when looking for unstaged changes, it does not need to read every file on your disk. 但是,在查找未暂存的更改时,不需要读取磁盘上的每个文件。 Instead, it can look at the metadata stored in the index to determine what files to examine more closely (actually reading them). 相反,它可以查看存储在索引中的元数据,以确定要更仔细检查(实际读取它们)的文件。

If you use the git-ls-files command to examine the index, you can see this metadata: 如果使用git-ls-files命令检查索引,则可以看到以下元数据:

% git ls-files --debug worktree.c
worktree.c
  ctime: 1463782535:0
  mtime: 1463782535:0
  dev: 16777220 ino: 120901250
  uid: 501      gid: 20
  size: 5591    flags: 0

Now if you run git status , git will look at worktree.c on disk. 现在,如果您运行git status ,则git将查看磁盘上的worktree.c If the timestamps and filesize match, then git will assume that you have not changed this file. 如果时间戳和文件大小匹配,则git将假定您尚未更改此文件。

If, however, the timestamps and filesize do not match, then git will look more closely at the file to determine if you have changed it or not. 但是,如果时间戳和文件大小匹配,则git会更仔细地查看文件,以确定您是否进行了更改。

So git does "thrash" the disk, but in a much more limited manner than if you did something like tf reconcile to examine your changes. 因此git 确实会 “破坏”磁盘,但是以比tf reconcile来检查更改的方式更为有限。 (TFVC, of course, was designed to deal with very large working trees and should never touch your disk if you're using it correctly.) (当然,TFVC是为处理非常大的工作树而设计的,如果正确使用它, 切勿触摸磁盘。)

And yes - Visual Studio does have some magic in it. 是的-Visual Studio 确实具有一些魔力。 It runs a background filesystem watcher in both your working directory and some parts of the Git repository. 它在您的工作目录和Git存储库的某些部分中运行一个后台文件系统监视程序。 When it notices a change in your working directory, it will re-compute the git status . 当发现工作目录发生更改时,它将重新计算git status It also looks at changes to branches in the Git repository to know when you've switched branches or to recompute the status of your local repository with your remote. 它还会查看Git存储库中分支的更改,以了解您何时切换了分支,或使用遥控器重新计算本地存储库的状态。

Git's process of git status is very lightweight. Git的git status过程非常轻巧。

git status checks the index (also known as staging area, before you run git add ) and the working directory (after git add but before git commit ), then compares those files with the last committed version. git status检查索引(也就是临时区域,在运行git add之前)和工作目录(在git add但在git commit之前),然后将这些文件与最后提交的版本进行比较。 Instead of having to go through every file in the repository, Git first checks these areas to see what to look up in the most recent commit. Git首先不必检查存储库中的每个文件,而是先检查这些区域以查看在最新提交中要查找的内容。

git diff works similarly. git diff工作原理与此类似。 I suggest looking here for more information. 我建议在这里查找更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Windows和Mac上开发时(如何修改文件),如何在git上管理Nuget仓库配置文件? - How to manage Nuget repositories config files on git, when developing on Windows and Mac (files always modified)? 在Windows上使用Git,如何创建显示修改文件,提交消息,作者和日期的报告 - Using Git on Windows, how can I create reports that show modified files, commit messages, author and date Git:如何在Windows上忽略文件? - Git: How to ignore files on Windows? Git for Windows使用哪些证书文件 - Which cert files does Git for Windows use git stash离开修改过的文件? - git stash leaving modified files? 从Windows复制了一堆文件到ubuntu服务器,现在所有文件都显示为git,带有^ M - Copied a bunch of files from windows to ubuntu server and now all the files are showing modified in git with ^M 使用git ls-files复制修改后的文件的Windows命令是什么? - What is the Windows command for using git ls-files to copy modified files? Jenkins无法从Windows凭据管理器检测到GIT凭据 - Jenkins does not detect GIT credentials from Windows Credential manager 实时Windows Server上的Git-尝试从存储库中提取但本地文件已被修改 - Git on live Windows Server - Trying to pull from the repo but local files already modified Windows上的文件上次修改日期 - Files last modified date on Windows
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM