为什么"git status"运行过滤器? [英] Why does 'git status' run filters?

查看:63
本文介绍了为什么"git status"运行过滤器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将git repo克隆到现有目录( $ HOME ,用于管理点文件).我正在进行裸克隆并重新配置它,因为我需要克隆到现有的 unclean 工作目录中.它有效,但是我发现 git status 尝试在首次使用时运行过滤器.为什么这样做,我该如何预防呢?

I need to clone a git repo into an existing directory ($HOME, for managing dotfiles). I'm doing a bare clone and reconfiguring it because I need to clone into an existing unclean working directory. It works, however I find that git status tries to run filters on first use. Why does it do that and how can I prevent it?

尝试一下:

# create a test repo
mkdir test && cd test
git init
echo hello > hello.txt
git add .
git commit -m 1
echo 'hello.txt filter=foo diff=bar' > .gitattributes
git add .
git commit -m 2

# clone it bare and configure it
mkdir ../test2 && cd ../test2
git clone --bare ../test .git
git config core.bare false
git config core.logallrefupdates true
git reset
git checkout .
git config filter.foo.clean foo
git config filter.foo.smudge foo
git config diff.bar.textconv bar

这很闷

$ git status
error: cannot run foo: No such file or directory
error: cannot fork to run external filter 'foo'
error: external filter 'foo' failed
On branch master
nothing to commit, working tree clean

这不是

$ git status
On branch master
nothing to commit, working tree clean

此外,最初快速连续多次执行 git status (即 git status; git status; git status)可能会导致多次失败.有时.

Also, initially doing git status multiple times in quick succession (i.e. git status; git status; git status) can yield multiple failures. Sometimes.

据我可以通过阅读更多内容进行确认,应该仅在签入和签出文件时运行.

As far as I can confirm by much reading, the filters should only run when checking files in and out.

那么为什么 git status 运行它们?

推荐答案

仅在签入/签出期间运行过滤器的想法是善意的谎言.这是为了使过滤器更易于理解.

The idea that filters only run during checkin/checkout is something of a white lie. It's meant to make filters more explicable.

尽管如此,实际上,过滤器是在索引和工作树之间移动文件时运行的(以及在现代版本的Git中,当通过中的-path = 选项请求时)git show git cat-file git hash-object :其中一些是直接从存储库到stdout或从stdin到存储库的过渡.这主要是等同于签入/签出时间.但是由于索引的缓存方面, git status 也具有特殊的区别.

In fact, though, filters run when moving files between the index and work-tree (and also, in sufficiently modern versions of Git, when requested with --path= options in git show and git cat-file and git hash-object as well: some of these are transitions directly from repository to stdout, or stdin to repository). This is mostly equivalent to checkin/checkout time. But git status has special dispensation as well, due to the cache aspect of the index.

出于性能方面的考虑,Git想知道工作树中的任何文件相对于索引中的版本是否可能是脏"的.Git假定 stat st_mtime (通常具有一秒的分辨率), 1 可以用于此目的:如果文件(工作树条目)的st_mtime 时间比索引条目中保存的 st_mtime 早索引条目是最新的并且是干净的":在应用干净的过滤器等之后,索引中的内容与工作树中的内容匹配.

For performance reasons, Git wants to know whether any file in the work-tree might be "dirty" with respect to the version in the index. Git assumes that the stat value st_mtime, which typically has one-second resolution,1 can be used for this purpose: if the st_mtime time of the file—the work-tree entry—is older than a saved st_mtime in an index entry, then the index entry is up to date and is "clean": what's in the index matches what's in the work-tree, after applying clean filters etc.

如果工作树条目的时间戳比保存的索引条目,则该文件肯定已被修改:索引条目可能不存在日期.它不是保证过期的内容,因为工作树文件的修改方式最终没有改变.但是显然有必要运行干净的过滤器(以及任何以CR/LF结尾的黑客行为).

If the time stamp of the work-tree entry is newer than the saved index entry, then the file has definitely been modified: the index entry may be out of date. It's not guaranteed out of date, as the work-tree file may have been modified in a way that ultimately made no change. But it's clearly necessary to run the clean filter (and any CR/LF line ending hackery).

如果两个时间戳相同,则工作树条目不确定.(尽管种族肮脏"同样准确,但Git称其为种族干净")

If the two time stamps are the same, the work-tree entry is indeterminate. (Git calls this "racily clean" although "racily dirty" would be equally accurate.)

在所有这些情况下, git status 将在工作树文件上运行clean过滤器(以及所有输入到Git方向的CR/LF修改),以计算新的哈希值.如果新哈希与索引哈希匹配,则Git可以并且将更新索引条目以将文件标记为实际上是干净的".现在,下次您执行某项操作时,Git不必运行干净的过滤器.

In all these cases, git status will run the clean filter (and any input-to-Git direction CR/LF modifications) over the work-tree file to compute a new hash. If the new hash matches the index hash, Git can and will update the index entry to mark the file as "actually clean". Now, the next time you do something, Git won't have to run the clean filter.

除非,即是在 st_mtime stat字段的分辨率内完成所有操作.在这种情况下,索引条目会非常干净",Git必须再次尝试.这就是您在这里观察到的.

Unless, that is, you do it all within the resolution of the st_mtime stat field. In that case, the index entry winds up "racily clean" and Git has to try again. This is what you are observing here.

(顺便说一下,注意 git status 运行两个差异:一个从 HEAD 到索引,一个从索引到工作-tree.第二个差异从索引的缓存方面大为受益.索引现在还可以存储有关未缓存的文件和目录的信息!)

(Note, by the way, that git status runs two diffs: one from HEAD to index, and one from index to work-tree. It's that second diff that benefits hugely from the cache aspect of the index. The index can now also store information about uncached files and directories, too!)

1 某些 stat 调用可以提供亚秒级的精度,但是由于各种原因,索引/缓存项通常只存储1秒分辨率的时间戳.

1Some stat calls give sub-second precision, but for various reasons, the index / cache entry only stores the 1-second resolution time stamp anyway, normally.

有关(更多)详细信息,请参见技术文档中的 racy-git.txt 文件.

For (much) more on this, see the racy-git.txt file in the technical documentation.

这篇关于为什么"git status"运行过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆