获得提示,以指示Zsh中的Git分支


76

我在.zshrc中未按提示分别运行以下代码。这表明我显然没有一个名为__git_ps1的程序。它不在MacPorts中。

#1

PROMPT="$(__git_ps1 " \[\033[1;32m\] (%s)\[\033[0m\]")\$"$

#2

PROMPT="$(__git_ps1 " (%s)")\$"$

#3

# Get the name of the branch we are on
git_prompt_info() {
  branch_prompt=$(__git_ps1)
  if [ -n "$branch_prompt" ]; then
    status_icon=$(git_status)
    echo $branch_prompt $status_icon
  fi
}

# Show character if changes are pending
git_status() {
  if current_git_status=$(git status | grep 'added to commit' 2> /dev/null); then
    echo "☠"
  fi
}
autoload -U colors
colors
setopt prompt_subst
PROMPT='
%~%{$fg_bold[black]%}$(git_prompt_info)
→ %{$reset_color%}'

如何获得显示Git分支名称的提示?


Answers:


77

__git_ps1来自git-completion.bash。在zsh中,您可能必须提供自己的函数来确定当前目录的git分支。关于zsh的git提示,有很多博客文章

您只需:

  • 提供分支名称的功能
  • 启用提示(命令)替换
  • 将功能添加到提示

例如

git_prompt() {
 ref=$(git symbolic-ref HEAD | cut -d'/' -f3)
 echo $ref
}
setopt prompt_subst
PS1=$(git_prompt)%#
autoload -U promptinit
promptinit

更新:使用zsh vcs_info模块代替git_prompt()

setopt prompt_subst
autoload -Uz vcs_info
zstyle ':vcs_info:*' actionformats \
    '%F{5}(%f%s%F{5})%F{3}-%F{5}[%F{2}%b%F{3}|%F{1}%a%F{5}]%f '
zstyle ':vcs_info:*' formats       \
    '%F{5}(%f%s%F{5})%F{3}-%F{5}[%F{2}%b%F{5}]%f '
zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat '%b%F{1}:%F{3}%r'

zstyle ':vcs_info:*' enable git cvs svn

# or use pre_cmd, see man zshcontrib
vcs_info_wrapper() {
  vcs_info
  if [ -n "$vcs_info_msg_0_" ]; then
    echo "%{$fg[grey]%}${vcs_info_msg_0_}%{$reset_color%}$del"
  fi
}
RPROMPT=$'$(vcs_info_wrapper)'

5
git_prompt是错误的,如果您的分支带有/则不起作用。使用cut -d'/' -f3-代替。
下雨了

1
谢谢!,这有效。您能否解释一下这些神秘的zstyle命令的作用?
balki

1
@balki为前景%F{n}启用ANSI颜色 n,并%f禁用前景颜色。例如,如果忽略颜色,则formats格式%F{5}(%f%s%F{5})%F{3}-%F{5}[%F{2}%b%F{3}]%f 变为(%s)-[%b]。在%s得到由VC系统(例如GIT)代替,%b得到由当前分支取代。
ntc2

1
@balki将(sv[nk]|bzr)在子模式branchformat限制了它svnsvkbzr。这意味着这些系统应使用branch:revision而不是默认值branch。由于该enablebzr不支持,因此此bzr限制为“死代码”。前三行是从ZSH文档逐字复制的,但最后一行是其他人添加的,这可能解释了无效代码。
ntc2

1
@balkiactionformats变成(%s)-[%b|%a]无视颜色。在特殊操作期间使用此格式,并%a描述操作。恕我直言,这是最有用的功能:例如,对于git,它告诉您何时处于重定基数的中间(在尝试解决合并冲突时,我常常忘记了这一点)。
ntc2

43

这是zsh的扩展git提示:zsh-git-prompt

替代文字


1
爱它!完善。很好的工作,现在是我自己的dotfiles存储库中的子模块。:)
贾斯汀力

2
您的方法与vcs_info相比如何?看来您的脚本正在重塑方向盘?(虽然并没有阻止我使用它,但我没有意识到vcs_info)
伤害到

在采购过程中遇到问题:“无法识别的修饰符'A'”。zsh 4.2.6(x86_64-redhat-linux-gnu)。这是一个已知问题吗?
Timofey

存储库不再维护-似乎有些人接管了这里:github.com/zsh-git-prompt/zsh-git-prompt编辑链接的答案
Ev0oD

无法使其与我上面提到的回购一起运行。发现ohmyzsh做得很好,请参阅stackoverflow.com/a/63919265/1920149
Ev0oD

38

ko-dos的回答很好,但是我更喜欢一个比git更能识别提示的提示,而不是他使用的提示。具体来说,我喜欢提示本身中的暂存,未暂存和未跟踪的文件通知。使用他的答案和zsh vcs_info示例,我得出以下结论

setopt prompt_subst
autoload -Uz vcs_info
zstyle ':vcs_info:*' stagedstr 'M' 
zstyle ':vcs_info:*' unstagedstr 'M' 
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:*' actionformats '%F{5}[%F{2}%b%F{3}|%F{1}%a%F{5}]%f '
zstyle ':vcs_info:*' formats \
  '%F{5}[%F{2}%b%F{5}] %F{2}%c%F{3}%u%f'
zstyle ':vcs_info:git*+set-message:*' hooks git-untracked
zstyle ':vcs_info:*' enable git 
+vi-git-untracked() {
  if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == 'true' ]] && \
  [[ $(git ls-files --other --directory --exclude-standard | sed q | wc -l | tr -d ' ') == 1 ]] ; then
  hook_com[unstaged]+='%F{1}??%f'
fi
}


precmd () { vcs_info }
PROMPT='%F{5}[%F{2}%n%F{5}] %F{3}%3~ ${vcs_info_msg_0_} %f%# '

这将创建一个提示,以模仿的彩色输出git status -s(可以在.gitconfig文件中配置)。图片也许在这里最有帮助:

提示

git status -s

在此处输入图片说明

如果你不喜欢彩色输出,或宁愿其它字符或提示建设,只是改变了stagedstrunstagedstrhook_com[unstaged]在上面的代码值。


1
这是特定于git的绝佳用法vcs_info。但有一两件事:git status。我git ls-files --other --directory --exclude-standard | sed q | wc -l | tr -d ' '改用了,速度更快。
Thomas Upton 2014年

不错的修改。相应地更新。
Christopher

--directory标志实际上可能不是必需的。我发现这很烦人,因为git通常会忽略空目录。
Thomas Upton 2014年

遇到相同的问题(即,git忽略的空目录导致??出现在提示中)。通过--no-empty-directorygit ls-files命令中添加标志来修复。
szeryf 2014年

33

当我混入回车键时,许多这些解决方案对我来说似乎很慢,因此这是一个基本且快速的选项:

parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}

setopt PROMPT_SUBST
PROMPT='%9c%{%F{green}%}$(parse_git_branch)%{%F{none}%} $ '

您会收到如下提示: ~/dev/project (feature-branch) $


5
git symbolic-ref --short HEAD 2> /dev/null将为您提供需要较少解析的答案。
ssokolow

8

因为我们的分支名称很长,所以我只是重新命名了。如果该字符超过35个字符,它将用省略号截断。

parse_git_branch() {
    git_status="$(git status 2> /dev/null)"
    pattern="On branch ([^[:space:]]*)"
    if [[ ! ${git_status} =~ "(working (tree|directory) clean)" ]]; then
        state="*"
    fi
    if [[ ${git_status} =~ ${pattern} ]]; then
      branch=${match[1]}
      branch_cut=${branch:0:35}
      if (( ${#branch} > ${#branch_cut} )); then
          echo "(${branch_cut}…${state})"
      else
          echo "(${branch}${state})"
      fi
    fi
}

setopt PROMPT_SUBST
PROMPT='%{%F{blue}%}%9c%{%F{none}%}$(parse_git_branch)$'

(我为此感到骄傲而感到尴尬。)


1

对于对维护的现成解决方案感兴趣的任何人,请安装https://github.com/ohmyzsh/ohmyzsh-默认情况下,它具有git插件。我一直在寻找这样的东西-不用脑子预先创建的配置,效果很好。


1

对于已经不想使用zshconfig和以外的内容的读者来说,这已经有了许多不错的答案git

但是,我发现自己只是想要

working-directory (git-branch-color-if-uncommitted) %          24h-timestamp
git_branch_test_color() {
  local ref=$(git symbolic-ref --short HEAD 2> /dev/null)
  if [ -n "${ref}" ]; then
    if [ -n "$(git status --porcelain)" ]; then
      local gitstatuscolor='%F{red}'
    else
      local gitstatuscolor='%F{green}'
    fi
    echo "${gitstatuscolor} (${ref})"
  else
    echo ""
  fi
}
setopt PROMPT_SUBST
PROMPT='%9c$(git_branch_test_color)%F{none} %# '

# add 24h time the right side
RPROMPT='%D{%k:%M:%S}'

提示着色示例

这是由

  • $()通过设置允许包含函数()PROMPT_SUBST(感谢Phil的2017年回答!
  • 声明一个函数git_branch_test_color来调用git分支ref ..,如果当前目录是git存储库,则是否成功(测试stdout)
    (感谢symbolic-refarg!的几点评论)
    • 如果不是git repo,则仅回显一个空字符串 ""
  • 如果初始调用确实成功(是否已经收集了stdout),则当前目录为git目录
    git status --porcelain用于确定是否已更改任何文件或新建/删除了文件
    • 绿色前缀不变
    • 更改的红色前缀(无论可能是什么)

请注意,所有此类提示在挂载目录上都可能很慢(尤其是通过sshfs)。如果遇到这种情况,我建议尽可能对这些目录进行特殊处理(也许创建一个新的shell函数以检查cd是否在您的集合中)或始终挂载在同一路径中并忽略它(例如带有vcs_info


0

谢谢你的链接!

我根据他们做出了以下提示

     # get the name of the branch we are on
     git_prompt_info() { 
         git branch | awk '/^\*/ { print $2 }'
     }
     get_git_dirty() { 
       git diff --quiet || echo '*'
     }

     autoload -U colors
     colors     
     setopt prompt_subst

     PROMPT='%{$fg[blue]%}%c %{$fg_bold[red]%}$(git_prompt_info)$(get_git_dirty)%{$fg[blue]%} $ %{$reset_color%}'                                           

     RPROMPT='%{$fg[green]%}%1(j.%j.)'        

请提出任何改进建议。


4
不要使用git-branch。它是瓷器,用于UI,而不是用于脚本。使用git-symbolic-ref和BR = $ {BR#refs / heads /}
JakubNarębski09年

@Jakub:谢谢你指出这一点!---我刚刚观察到git-branch会导致非git目录的错误。
莱奥波德·赫兹(LéoLéopoldHertz)2009年

5
@JakubNarębski:您也可以这样做git symbolic-ref --short HEAD,这将为您删除“ refs / heads /”业务。
塔纳托斯

0

如果您所有的提示看起来都不错,但是不起作用,例如:

function git_branch(){                                                                                                                 
    ref=$(git symbolic-ref --short --quiet HEAD 2>/dev/null)        
    if [ -n "${ref}" ]; then                                                    
        echo "(""$ref"")"                                                       
    fi                                                                          
}                                                                               
                                                                                
setopt PROMPT_SUBST                                                             

PROMPT="%{$fg[red]%}%n%{$reset_color%}@%{$fg[blue]%}%m:%{$fg[yellow]%}%1~%{$reset_color%} %{%F{green}%}$(git_branch)%{%F{none}%}$ "

PROMPT必须设置为使用单引号而不是双引号引起来的字符串。

PROMPT='%{$fg[red]%}%n%{$reset_color%}@%{$fg[blue]%}%m:%{$fg[yellow]%}%1~%{$reset_color%} %{%F{green}%}$(git_branch)%{%F{none}%}$ '
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.