【问题标题】:Check if current directory is a Git repository检查当前目录是否为 Git 存储库
【发布时间】:2011-01-11 22:09:45
【问题描述】:

我正在写一系列zsh中的Git管理脚本。

如何检查当前目录是否为 Git 存储库? (当我不在 Git 存储库中时,我不想执行一堆命令并得到一堆 fatal: Not a git repository 响应)。

【问题讨论】:

  • 您是否查看了 bash 完成文件(在 contrib/completion/git-completion.bash 中)以获得灵感?我使用 __git_ps1 命令作为 bash 提示符的一部分。事实上,大部分内容都来自 zsh。 __gitdir 函数可能是你想要的。
  • @jabbie:你为什么不回答这个问题?
  • 你检查过 zsh 发行版中的函数了吗?
  • 注意:当前的答案都没有考虑$GIT_DIR 或$GIT_WORK_TREE 环境变量,或者它们如何交互。

标签: git zsh


【解决方案1】:

从bash补全文件中复制而来,下面是一种幼稚的做法

# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
# Distributed under the GNU General Public License, version 2.0.

if [ -d .git ]; then
  echo .git;
else
  git rev-parse --git-dir 2> /dev/null;
fi;

您可以将其包装在一个函数中,也可以在脚本中使用它。

浓缩成适合bash和zsh

的单行条件
[ -d .git ] && echo .git || git rev-parse --git-dir > /dev/null 2>&1

【讨论】:

  • @William Pursell 为什么在不需要的时候分叉?主要是为了在微不足道的情况下提高速度。
  • 答案应该更新为使用git rev-parse --is-inside-git-dir。我个人在设置我的 PS1 之前使用git rev-parse --is-inside-work-tree。
  • @juliohm --is-inside-git-dir 仅在您实际位于存储库的 .git 目录 中时才会返回 true。我不认为 OP 正在寻找那个。
  • --is-inside-work-tree 和 --is-inside-git-dir 在 git 存储库之外都不起作用。见:groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
  • 如果 git 目录不是.git,这将失败。为了健壮性,省略[ -d .git ],只使用git rev-parse ...。
【解决方案2】:

你可以使用:

git rev-parse --is-inside-work-tree

如果您在 git repos 工作树中,它将打印 'true'。

请注意,如果您不在 git repo 之外,它仍会将输出返回到 STDERR(并且不打印“false”)。

取自这个答案:https://stackoverflow.com/a/2044714/12983

【讨论】:

  • 这是最简单的检查方法。
  • 对于没有工作树的裸存储库,这仍然会打印 false
  • 这里不考虑子目录。我需要验证 git rev-parse --show-toplevel 是否与我正在检查的子文件夹匹配
  • 选择的答案甚至没有打印出任何东西。这个有效。
  • 我们可以这样做吗:if git rev-parse --is-inside-work-tree &gt; /dev/null 2&gt;&amp;1; then like William Pursells answer?
【解决方案3】:

使用 git rev-parse --git-dir

if git rev-parse --git-dir > /dev/null 2>&1; then
  : # This is a valid git repository (but the current working
    # directory may not be the top level.
    # Check the output of the git rev-parse command if you care)
else
  : # this is not a git repository
fi

编辑:git-rev-parse 现在(从 1.7.0 开始)支持--show-toplevel,因此您可以使用if test "$(pwd)" = "$(git rev-parse --show-toplevel)" 来确定当前目录是否为顶级目录。

【讨论】:

    【解决方案4】:

    或者你可以这样做:

    inside_git_repo="$(git rev-parse --is-inside-work-tree 2>/dev/null)"
    
    if [ "$inside_git_repo" ]; then
      echo "inside git repo"
    else
      echo "not in git repo"
    fi
    
    【解决方案5】:

    基于@Alex Cory's answer:

    [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]
    

    不包含任何冗余操作,工作于-e模式。

    • As @go2null noted,这在裸仓库中不起作用。如果您出于某种原因想要使用裸仓库,您可以只检查 git rev-parse 是否成功,而忽略其输出。
      • 我不认为这是一个缺点,因为上面的行是为脚本编写的,实际上所有git 命令只在工作树内有效。因此,出于编写脚本的目的,您很可能不仅对“git repo”感兴趣,而且对工作树感兴趣。

    【讨论】:

    • 这在裸 git repo 中失败
    • 与其检查输出,不如检查返回值。根本不要调用[。只需执行if git rev-parse --is-inside-work-tree; then ...(根据需要进行重定向。)
    • @WilliamPursell 检查退出值在这里不起作用:stackoverflow.com/questions/2180270/…
    • @Ivan_pozdeev 取决于您对“工作”的定义。在这种情况下,我会说检查返回值确实有效,而检查输出则无效。无论哪种情况,从在 shell 中编写代码的最佳实践的角度来看,检查返回值更为合适。
    • @ivan_pozdeev 谢谢,但请注意,即使在 Linux 下,也不是所有用户都使用 bash(== 在 zsh 中也无效)。
    【解决方案6】:

    不确定是否有公开访问/记录的方式来做到这一点(有一些内部 git 函数可以在 git 源本身中使用/滥用)

    你可以这样做;

    if ! git ls-files >& /dev/null; then
      echo "not in git"
    fi
    

    【讨论】:

      【解决方案7】:

      另一种解决方案是检查命令的退出代码。

      git rev-parse 2> /dev/null; [ $? == 0 ] && echo 1
      

      如果您在 git 存储库文件夹中,这将打印 1。

      【讨论】:

      • 请注意,即使您在 .git 目录中,它也会有 rc 0 -- 您可能想要也可能不想要。
      • Git 写得很清楚,所以你可以关闭你不想要的文件,git rev-parse 2&gt;&amp;-。
      • [ $? == 0 ] 在这里是多余的;这是&amp;&amp; 已经进行的隐含测试。上述命令等价于git rev-parse 2&gt;/dev/null &amp;&amp; echo 1。
      【解决方案8】:

      这个答案提供了一个示例 POSIX shell 函数和一个用法示例来补充@jabbie 的answer。

      is_inside_git_repo() {
          git rev-parse --is-inside-work-tree >/dev/null 2>&1
      }
      

      git 如果它位于 git 存储库中,则返回错误级别 0,否则返回错误级别 128。 (如果它在 git 存储库中,它还会返回 true 或 false。)

      使用示例

      for repo in *; do
          # skip files
          [ -d "$repo" ] || continue
          # run commands in subshell so each loop starts in the current dir
          (
              cd "$repo"
              # skip plain directories
              is_inside_git_repo || continue
              printf '== %s ==\n' "$repo"
              git remote update --prune 'origin' # example command
              # other commands here
          )
      done
      

      【讨论】:

      • 不够。在.git 内部,它会成功,但会打印false。
      • @ivan_pozdeev: 如果git rev-parse --is-inside-work-tree 返回true 或false 那么它是 在一个git repo 中,这就是函数返回的内容。即函数正确
      • 展开,看答案中的描述,git返回的值被忽略,使用的是errorlevel。
      【解决方案9】:

      为什么不使用退出代码?如果当前目录下存在 git 仓库,则git branch 和git tag 命令返回退出码 0;否则,将返回非零退出代码。这样,您可以确定 git 存储库是否存在。简单地说,你可以运行:

      git tag > /dev/null 2>&1
      

      优势:便携。它适用于裸存储库和非裸存储库,以及 sh、zsh 和 bash。

      说明

      1. git tag:获取存储库的标签以确定是否存在。
      2. &gt; /dev/null 2&gt;&amp;1:阻止打印任何内容,包括正常和错误输出。

      TLDR (Really?!):check-git-repo

      例如,您可以创建一个名为check-git-repo 的文件,其内容如下,使其可执行并运行:

      #!/bin/sh
      
      if git tag > /dev/null 2>&1; then
          echo "Repository exists!";
      else
          echo "No repository here.";
      fi
      

      【讨论】:

      • &amp;&amp; [ $? -eq 0 ] 是多余的,尤其是如果您已经在 if 中。
      【解决方案10】:

      # 检查是否是 git repo

      if [ $(git rev-parse --is-inside-work-tree) = true ]; then
          echo "yes, is a git repo"
          git pull
      else
          echo "no, is not a git repo"
          git clone url --depth 1
      fi
      

      【讨论】:

      • 这不是最佳实践。如果在工作目录之外运行,您将在 stderr 上得到“致命:不是 git 存储库(或任何父目录):.git”,在 stdout 上显示“不,不是 git 存储库”。这里根本不需要调用[。只需:if git rev-parse --is-inside-work-tree &gt; /dev/null 2&gt;&amp;1; then ....
      • 就我而言,我对此很满意,我想在我的日志中跟踪这个故障。干杯!
      【解决方案11】:

      这对我有用。您仍然会收到错误,但它们很容易被压制。它也适用于子文件夹!

      git status >/dev/null 2>&1 && echo Hello World!
      

      如果你需要有条件地做更多事情,你可以把它放在 if then 语句中。

      【讨论】:

      • 在很多情况下可能已经足够了,但它在裸 git repo 上失败了。
      • git status 在大型/旧仓库上可能会非常慢。我不会将它用于此目的。
      • @henrebotha 我完全同意,我仍在这样做,因为无论如何我都需要输出进行处理:git_status="$(git status --porcelain --branch 2&gt; /dev/null)"; if [ $? -eq 0 ]; then echo something with $git_status; fi
      【解决方案12】:
      if ! [[ $(pwd) = *.git/* || $(pwd) = *.git ]]; then 
        if type -P git >/dev/null; then
          ! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
           printf '\n%s\n\n' "GIT repository detected." && git status
          }
        fi
      fi
      

      谢谢ivan_pozdeev,现在我有一个测试,如果在 .git 目录中代码不会运行,所以没有打印出错误或错误的退出状态。

      "! [[ $(pwd) = .git/ || $(pwd) = *.git ]]" 测试你是否不在里面.git repo 然后它将运行 git 命令。内置的 type 命令用于检查你是否安装了 git 或者它是否在你的 PATH 中。请参阅帮助类型

      【讨论】:

        【解决方案13】:

        在 linux 的终端或 Windows 的 cmd 中打开该目录并输入 git status,这在 2021 年应该足以告诉您您在 git repo 中并且您有 x 的分支数量和 x 数量提交。

        【讨论】:

          猜你喜欢
          • 2020-11-05
          • 2017-01-23
          • 1970-01-01
          • 2016-04-03
          • 1970-01-01
          • 2020-02-05
          • 2015-10-21
          • 2014-04-22
          • 1970-01-01
          相关资源
          最近更新 更多