在bash中获取git状态的最快方法

时间:2012-06-20 15:02:38

标签: git bash

有一段时间我一直在我的bash的PS1提示中使用__git_ps1函数 (PS1='\w$(__git_ps1)')。现在我想根据分支对它进行着色 状态。

我编写了一个bash函数,用于检查当前分支是否被修改,以及 颜色为红色或白色,具体取决于状态。问题是它使用git status来检查状态(这是我知道的唯一方法),那就是几个 比__git_ps1慢一倍,这足以导致烦人的延迟 我正在使用提示(我的上网本非常弱)。

所以我问:有没有更快的方法来检查当前git文件夹的状态? __git_ps1比手动解析git branch快得多,所以我在想 可能还有一些其他隐藏的git函数。

7 个答案:

答案 0 :(得分:6)

不完全是你的回答,但是bash-completion有内置功能。<​​/ p>

如果将bash ENV GIT_PS1_SHOWDIRTYSTATE设置为非空值,则分支名称旁边将显示未分段(*)和分段(+)更改。您可以使用bash.showDirtyState变量配置此每个存储库,一旦启用GIT_PS1_SHOWDIRTYSTATE,该变量默认为true。

通过将GIT_PS1_SHOWSTASHSTATE设置为非空值,您还可以查看当前是否存在某些内容。如果有什么东西被藏起来,那就是&#39; $&#39;将显示在分支名称旁边。

如果您想查看是否有未跟踪的文件,则可以将GIT_PS1_SHOWUNTRACKEDFILES设置为非空值。如果有未跟踪的文件,那么&#39;%&#39;将显示在分支名称旁边。

虽然启用此功能但不确定速度是否会降低。 如果你想做着色:

分阶段文件:

if git rev-parse --quiet --verify HEAD >/dev/null; then
 git diff-index --cached --quiet HEAD -- || color for staged changes
else
  color unstaged changes
fi

藏匿文件

git rev-parse --verify refs/stash >/dev/null 2>&1 && color for stashed files

未跟踪文件

if [ -n "$(git ls-files --others --exclude-standard)" ]; then
  Color untrack files
fi

上面的代码片段来自bash-completion脚本。

答案 1 :(得分:4)

如果工作目录有更改,则

git diff --quiet返回1,而git diff --quiet --cached对索引执行相同操作。

你可以用它来做:

git diff --quiet
    || echo "There be changes!"

答案 2 :(得分:3)

注意:Git 2.6 +(2015年第3季度)应加速__git_ps1状态:

commit dd160d7commit 6bfab99SZEDER Gábor (szeder)(2015年7月19日) (由Junio C Hamano -- gitster --合并于commit 461c119,2015年8月3日)

  

bash提示:更快的未跟踪状态指示器,带有未跟踪目录

     

如果启用了未跟踪状态指示器,__git_ps1()会运行“git ls-files”来查找未跟踪的文件。
  如果未跟踪的目录包含大量文件,这可能会非常慢,因为它列出了未跟踪目录中找到的所有文件,只是立即重定向到/dev/null。   这是由__git_ps1()运行的实际命令:

$ ls untracked-dir/ |wc -l
100000
$ time git ls-files --others --exclude-standard --error-unmatch \
  -- ':/*' >/dev/null 2>/dev/null

real    0m0.955s
user    0m0.936s
sys 0m0.016s
  

通过另外将“--directory --no-empty-directory”选项传递给“git ls-files”以仅显示非空未跟踪目录的名称而不是其所有内容来消除此延迟:

$ time git ls-files --others --exclude-standard --directory \
  --no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null

real    0m0.010s
user    0m0.008s
sys 0m0.000s
  

这跟随ea95c7b(完成:改进未跟踪目录   过滤文件名完成,2013-09-18,git 1.8.5)。

答案 3 :(得分:1)

! git diff-index --cached --quiet HEAD      # fastest staged-changes test
! git diff-files --quiet                    # fastest unstaged-changes test
! git diff-index --quiet          HEAD      # fastest any-changes test
stdbuf -oL git ls-files -o | grep -qs .     # fastest untracked-files test
git rev-parse -q --verify refs/stash >&-    # fastest any-stash test

如果对于未跟踪的文件而言,忽略状态很重要,请对未跟踪的文件使用--exclude-standard -oi,对未跟踪的文件使用--exclude-standard -o

我知道获得HEAD名称(分支名称或sha)的最快方法是

{ git symbolic-ref -q --short HEAD || git rev-parse -q --short --verify HEAD; } 2>&-

如果不在仓库中,它将留下返回码,因此您可以例如

if HEAD=`{ git symbolic-ref -q --short HEAD || git rev-parse -q --verify HEAD;  } 2>&-`
then
        : in a git repo, $HEAD is the branch name or sha
fi

请注意,未跟踪文件的测试取决于shopt -s lastpipe的{​​{1}}运行。 bashzsh在默认情况下以这种方式运行。

答案 4 :(得分:0)

我使用ksh并遇到同样的问题。最重要的是,我的Git存储库在NFS挂载上,使响应时间更慢。

要直接回答有关速度的问题,请尝试使用:

git ls-files -m
首次进入不同的存储库后,

似乎明显快于&#39; git status -s&#39;一旦进入存储库,操作系统和NFS缓存似乎会大大加快此命令的速度。当深入git工作目录树的底部叶子时,此命令似乎也非常快。

答案 5 :(得分:0)

所有带有git的解决方案最终都受git运行速度的限制。通过将一些fs-monitoring挂钩馈入git,可以使git本身比运行速度更快。

或者您可以减少工作量,例如--directory --no-empty-directory,但要走得更远:

答案 6 :(得分:-1)

您始终需要致电git --porcelain或类似的电话来获取状态信息。因此,提高速度的唯一方法是仅调用一次git,并确保处理尽可能快。

我用C ++编写了非常快速的git-status,并进行了最大程度的优化。它甚至具有一个--refresh-sec参数,如果先前的调用少于git秒之前,它将避免对--refresh-sec的额外调用。我认为这是最快的方法。

它用于zsh,但是您可以使其适应bash。而且速度非常快:https://gitlab.com/cosurgi/zsh-git-cal-status-cpp