2017-01-30 78 views
5

我需要克隆到现有的目录($HOME,用于管理点文件)的git回购。我正在做一个裸克隆并重新配置它,因为我需要克隆到现有的不干净的工作目录。 它的工作原理,但是我发现git status试图在第一次使用时运行过滤器。为什么要这样做,我该如何预防它?为什么'git status'运行过滤器?

试试这个:

# 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 

这borks

$ 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)可以产生多个失败,有时候,

据我所知,可以通过much reading进行确认,只有在检查输入和输出文件时,过滤器才会运行。

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

+0

你的'git --version'是什么? –

+0

git版本2.11.0 – starfry

+0

顺便说一句,我不会(也不要)以这种方式管理点文件。相反,我的主目录中有一个名为'Dotfiles'的Git目录,它是一个普通的非裸树,然后将'.whatever'符号链接到''Dotfiles/whatever'。 – torek

回答

2

仅在签入/签出期间运行过滤器的想法是white lie。这意味着要使过滤器更易于解释。

事实上,虽然过滤索引和工作树之间移动文件时运行(也,Git中充分现代版本,当与git show--path=选项和git cat-filegit hash-object以及要求:其中有些是直接从存储库转换为stdout,或者stdin转换为存储库)。这是主要是相当于签入/结帐时间。但由于索引的缓存方面,git status也具有特殊功能。

出于性能原因,Git想知道工作树中的任何文件是否可能与索引中的版本“脏”。 Git的假设stat价值st_mtime,通常具有一秒的分辨率,可以用于此目的:如果st_mtime时间文件的-the工作树入门比保存st_mtime年长在索引条目中,那么索引条目是最新的并且是“干净的”:索引中的内容与工作树中的内容匹配,在应用干净的过滤器之后等。

如果工作树的时间戳条目是,比保存的索引条目更新,那么文件肯定已被修改:索引条目可能是过时了。这不是保证已过时,因为工作树文件可能已被修改,最终没有改变。但显然需要运行清洁过滤器(以及任何结束hackery的CR/LF行)。

如果两个时间戳是相同的,工作树条目是不确定的。 (Git称之为“racily clean”,虽然“racily dirty”同样准确。)

在所有这些情况下,git status将在工作树文件上运行clean filter(以及任何input-to-Git direction CR/LF修改)以计算新的散列值。如果新散列与索引散列匹配,Git可以并且将更新索引条目以将文件标记为“实际上干净”。现在,当你下一次做某件事时,Git不必运行干净的过滤器。

除非,即在st_mtime stat字段的分辨率范围内完成所有操作。在这种情况下,索引条目会变得“很干净”,Git必须再试一次。这是你在这里观察的内容。

(注意,顺便说一句,那git status运行来进行比较:一个从HEAD索引,一个来自索引工作树就这么从索引缓存方面获得巨大的好处第二差异的。指数现在还可以存储关于未缓存文件和目录,太!)


一些stat电话给亚秒级的精度,但由于种种原因,该指数/缓存项只存储1无论如何,第二分辨率时间戳n ormally。

有关(更多)更多信息,请参见the racy-git.txt file in the technical documentation

+0

很好的解释!它也解释了为什么'touch hello.txt'使'git status'运行过滤器。它解释了为什么如果文件时间戳更改和状态检查之间的时间太短(<1s),它们又会重新运行。给出这个解释,我会假设没有办法阻止过滤器运行(在我的情况下,过滤器将失败,直到提供加密密钥)。在这种情况下,我的解决方案是'sleep 1 && git status&>/dev/null'是我希望的最好的...? – starfry

+0

该解决方法应该可行。不过,我不知道为什么要加密这些东西。 – torek

+0

私钥,API密钥等。我只在每个文件的基础上隐藏敏感的东西。 – starfry

相关问题