为什么我的git涂抹过滤器速度慢?

时间:2015-05-13 21:30:53

标签: git

我在git中有以下过滤器(我已将它们扩展到行以获得更多可读性):

git config --global filter.lastcommit.smudge 
'IFS=""; 
lastcommit=`git log -1 --format="%H" -- %f`; 
filename=$(basename %f); 
while read -r; 
do 
    line="${REPLY//\$Revision\$/\$Revision: $lastcommit\$}";
    line="${line//\$RCSfile\$/\$RCSfile: $filename\$}"; 
    echo $line; 
done'

git config --global filter.dater.smudge 
'IFS=""; myDate=`git log --pretty=format:"%cI" -1 --format="%H" -- %f`; 
while read -r; 
    do line="${REPLY//\$Date\$/\$Date: $myDate\$}"; 
    echo $line; 
done'

当我签出分支时,过滤器使用.gitattributes文件在三个目录中的大约~260 +文件上运行,但是每个文件可能需要几秒钟才能执行过滤:

Checking out files: 100% (6659/6659), done.
Branch ABC set up to track remote branch ABC from origin.
Switched to a new branch 'ABC'

real    4m42.334s
user    4m15.607s
sys 0m29.788s

有没有办法改善表现?

解决方案:我在阅读@torek回答后切换到使用sed。过滤器现在是:

git config --global filter.lastcommit.smudge 
'lastcommit=`git log -1 --format="%H" -- %f`; 
filename=$(basename %f); 
sed -e "s/\\\$Revision\\\$/\$Revision: $lastcommit\$/" 
    -e "s/\\\$RCSfile\\\$/\$RCSfile: $filename\$/";'

git config --global filter.dater.smudge 
'myDate=`git log --pretty=format:"%cI" -1 -- %f`; 
sed -e "s/\\\$Date\\\$/\$Date: $myDate\$/";'

收益非常可观:

~/panos > time git checkout ABC
Checking out files: 100% (6659/6659), done.
Branch ABC set up to track remote branch ABC from origin.
Switched to a new branch 'ABC'

real    0m12.956s
user    0m10.417s
sys    0m2.452s

我的印象是,使用sed的叉子比使用纯粹的bash更昂贵。结果是sed对文本替换更有效。我今天学到了一些东西

2 个答案:

答案 0 :(得分:3)

注意:我从未使用干净和涂抹过滤器,但这个概念看起来很简单。

您使用bash完全在read -r代码中进行涂抹操作。这是非常低效的(出于好的理由不适用于您的情况)并且可能是所有缓慢的原因。使用sed代替应该大大加快速度。

-e s/regexp/replacement/的{​​{1}}参数与此处的替换基本相同(您只需保护最终sed与正则表达式匹配),因此切换应该非常简单。 / p>

答案 1 :(得分:0)

注意:请注意直接在您的(涂抹/干净)脚本中访问%f文件内容。

commit 52db4b0Joey Hess (joeyh)(2016年8月3日) (由Junio C Hamano -- gitster --合并于commit 104985c,2016年8月8日)

现在.gitattributes documentation(Git 2。10,2016年第3季度)包括:

[filter "p4"]
    clean = git-p4-filter --clean %f
    smudge = git-p4-filter --smudge %f
  

请注意" %f"是正在处理的路径的名称   根据要过滤的版本,磁盘上的相应文件可能不存在,或者可能具有不同的内容   因此,涂抹和清除命令不应该尝试访问磁盘上的文件,而只是作为标准输入上提供给它们的内容的过滤器