【问题标题】:To get a prompt which indicates Git-branch in Zsh在 Zsh 中获得指示 Git-branch 的提示
【发布时间】:2010-11-10 20:08:57
【问题描述】:

我在 .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 分支名称的提示?

【问题讨论】:

标签: git zsh prompt


【解决方案1】:

__git_ps1 来自 git-completion.bash。在 zsh 中,您可能必须提供自己的函数来确定当前目录 git 分支。关于 zsh 的 git prompt 有不少 blog posts

你只需要:

  • 提供分支名称的函数
  • 启用提示(命令)替换
  • 将函数添加到您的提示中

例如

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)'

【讨论】:

  • git_prompt 是错误的,如果你有一个带有 / 的分支,它就不起作用。请改用cut -d'/' -f3-
  • 谢谢!,这行得通。你能解释一下那些神秘的 zstyle 命令的作用吗?
  • @balki %F{n} 启用 ANSI color 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 被当前分支替换。
  • @balki branchformat 上的(sv[nk]|bzr) 子模式将其限制为svnsvkbzr。这意味着这些系统应该使用branch:revision 而不是默认的branch。由于enable 行,不支持bzr,所以这个bzr 限制是“死代码”。前三行是从ZSH docs逐字复制的,但最后一行是别人添加的,这可能解释了死代码。
  • @balki actionformats 变为 (%s)-[%b|%a] 忽略颜色。此格式在特殊操作期间使用,%a 描述该操作。这是最有用的功能恕我直言:例如对于 git,它会告诉您何时处于 rebase 中间(我在尝试解决合并冲突时经常忘记这一点)。
【解决方案2】:

感谢您的链接!

我根据他们做了如下提示

     # 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.)'        

请提出任何改进建议。

【讨论】:

  • 不要使用 git-branch。它是瓷器,用于 UI,而不是用于脚本。使用 git-symbolic-ref 和 BR=${BR#refs/heads/}
  • @Jakub:感谢您指出这一点! --- 我刚刚观察到 git-branch 会导致非 git 目录出现错误。
  • @Jakub Narębski:您也可以使用git symbolic-ref --short HEAD,这将为您删除“refs/heads/”业务。
【解决方案3】:

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

【讨论】:

  • 爱它!完美的。非常好的工作,现在是我自己的 dotfiles repo 中的一个子模块。 :)
  • 您的方法与 vcs_info 相比如何?看来您的脚本正在重新发明轮子? (但并没有阻止我使用它,我不知道 vcs_info)
  • 在采购过程中遇到问题:“无法识别的修饰符‘A’”。 zsh 4.2.6 (x86_64-redhat-linux-gnu)。这是一个已知问题吗?
  • 不再维护存储库 - 似乎有些人接管了这里:github.com/zsh-git-prompt/zsh-git-prompt 编辑答案以链接到它
  • 无法使用我上面提到的 repo 运行它。发现 ohmyzsh 做得很好,见stackoverflow.com/a/63919265/1920149
【解决方案4】:

ko-dos 的回答很棒,但我更喜欢比他使用的提示更能感知 git 的提示。具体来说,我喜欢提示本身中的暂存、未暂存和未跟踪的文件通知。使用他的回答和zsh vcs_info examples, 我想出了以下内容:

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] 值。

【讨论】:

  • 这是vcs_info 的一个很好的特定于 git 的用法。不过有一件事:git status。我改用git ls-files --other --directory --exclude-standard | sed q | wc -l | tr -d ' ',而且速度更快。
  • 不错的修改。相应更新。
  • --directory 标志实际上可能不是必需的。我发现这很烦人,因为 git 通常会忽略空目录。
  • 遇到了同样的问题(即 git 忽略的空目录导致 ?? 出现在提示符中)。通过将--no-empty-directory 标志添加到git ls-files 命令来修复。
【解决方案5】:

我刚刚重做了我的,因为我们有很长的分支名称在工作。如果超过 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)$'

(我为自己的骄傲感到尴尬。)

【讨论】:

    【解决方案6】:

    在混合返回键时,这些解决方案对我来说似乎很慢,所以这里有一个基本且快速的选项:

    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) $

    【讨论】:

    • git symbolic-ref --short HEAD 2> /dev/null 将为您提供需要较少解析的答案。
    • 在哪里添加此代码?
    • @Manish 在你的 ~/.zshrc 文件中
    【解决方案7】:

    对于任何对维护的现成解决方案感兴趣的人,请安装 https://github.com/ohmyzsh/ohmyzsh - 它默认打开了一个 git 插件。我一直在寻找这样的东西 - 不费吹灰之力的预先创建的配置,效果很好。

    【讨论】:

      【解决方案8】:

      如果您的所有提示看起来都很好,但它不起作用,例如:

      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}%}$ '
      

      【讨论】:

        【解决方案9】:

        这已经有很多很好的答案,对于不想使用zsh 配置和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's 2017 answer!
        • 声明一个函数git_branch_test_color 为分支引用调用​​git ..如果当前目录是一个git 存储库,则通过这是否成功(测试stdout)
          (感谢 symbolic-ref arg 的一些 cmets!)
          • 如果不是git repo,只回显一个空字符串""
        • 如果初始调用确实成功(确实收集了标准输出),当前目录是一个 git 目录并且
          git status --porcelain 用于确定是否有任何文件已更改或是否为新文件/删除
          • 不变的绿色前缀
          • 更改的红色前缀(无论它们是什么)

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

        【讨论】:

          猜你喜欢
          • 2010-11-10
          • 1970-01-01
          • 2012-08-02
          • 2021-07-26
          • 2020-05-22
          • 2021-07-30
          • 2011-12-16
          相关资源
          最近更新 更多