0%

恼人的git prompt

写这篇的背景是当前很多shell都会有git prompt脚本,即对当前git仓库分支、改动情况的提示。
git分支命令的执行通常不会占用太多时间,但是改动情况的命令如git status或者简短版本的git status --porcelain则不然,特别是当仓库项目很大时,当你有以下我的使用场景时则更为糟糕。目前我个人的开发环境是windows+wsl,习惯上我会在win上通过git for windows的版本clone代码,然后在wsl里访问编辑,在这种场景下你会发现在wsl中的git status命令执行时间更长(这里我没深究其原因),特别是当你每敲一行命令shell都会去执行git status就更加恼人。
以下为个人的折腾记录,“可能”会不断更新不同shell的情况:

fish

当前我用的是fish,那么先折腾下fish:

fish_git_prompt

该函数是fish用于展示git目录状态的函数,官方介绍见这里。默认脚本在/usr/share/fish/functions/fish_git_prompt.fish,我们的目的只是要禁用git status,那么找到相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function __fish_git_prompt_informative_status
set -l stashstate 0
set -l stashfile "$argv[1]/logs/refs/stash"
if set -q __fish_git_prompt_showstashstate; and test -e "$stashfile"
set stashstate (count < $stashfile)
end

# Use git status --porcelain.
# This uses the "normal" untracked mode so untracked directories are considered as 1 entry.
# It's quite a bit faster and unlikely anyone cares about the number of files if it's *all* of the files
# in that directory.
# The v2 format is better, but we don't actually care in this case.
set -l stats (string sub -l 2 (git status --porcelain -z -unormal | string split0))
#...
end

function fish_git_prompt --description "Prompt function for Git"
#...

set -l informative (command git config --bool bash.showInformativeStatus)

#...
if test true = $inside_worktree
# Use informative status if it has been enabled locally, or it has been
# enabled globally (via the fish variable) and dirty or untracked are not false.
#
# This is to allow overrides for the repository.
if test "$informative" = true
or begin
set -q __fish_git_prompt_show_informative_status
and test "$dirty" != false
and test "$untracked" != false
end
set informative_status (__fish_git_prompt_informative_status $git_dir)
if test -n "$informative_status"
set informative_status "$space$informative_status"
end
#...
end

相关脚本都在上面了,逻辑是当前如果是git目录,并且informativetrue时才去使用git statusinformative会根据git config --bool bash.showInformativeStatus配置来,那么简单了,直接在git配置中把该配置禁用即可:

1
git config bash.showInformativeStatus false

使用何种级别的config那就看个人需求了。

fish_right_prompt

上面这个fish_git_prompt的issue可以在fish的github上翻到,fish_right_prompt这个就比较难找了,fish_right_prompt是作为右边提示的函数存在(见官网),fish的默认包里并没有这个函数的实现,但是如果你用了oh-my-fish这类主题工具,那么其脚本里可能会包含git status调用,如theme default中的~/.config/fish/functions/fish_right_prompt.fish 脚本:

1
2
3
4
5
6
function fish_right_prompt
#...

set -l porcelain_status (command git status --porcelain | string sub -l2)
#...
end

尴尬的发现没有任何判断,直接执行了git status,那我的解决方法也比较简单暴力,我不需要这个右提示符fish_right_prompt.fish:

1
2
3
4
5
6
function fish_right_prompt
if test "$fish_no_right_prompt" = true
return
end
#...
end

config.fish:

1
set -g fish_no_right_prompt "true"

当然直接改这个主题的脚本比较有问题,暂时先按照这个方式解决了。