【问题标题】:Check if local git repo is ahead/behind remote检查本地 git repo 是否在远程之前/之后
【发布时间】:2013-07-18 09:39:47
【问题描述】:

我正在开发一个 git 插件,我需要知道本地 repo 何时更改(可以提交更改),ahead(可以推送到远程) 或后面(可以从远程拉取)使用命令行。

这就是我目前正在做的事情:

  • 可以提交吗?

    如果git diff-index --name-only --ignore-submodules HEAD -- 返回一些东西, 那么是的,有更改要提交。

  • 可以推送吗?

    如果git status -sb 在其输出中包含单词ahead,那么是的,那里 是要推送的提交。

  • 可以拉吗?

    尚未实现。

can commit? 部分似乎工作正常。 可以推送吗?只对master分支有效,这是个大问题。

如何安全地检查每个分支上的 git repo 是否有要提交的更改、要推送的提交或需要 git pull

【问题讨论】:

  • 对于推送部分,您将拥有 Git 2.5+(2015 年第二季度)git for-each-ref --format="%(push:track)" refs/heads。查看更多in my answer there

标签: linux git bash shell github


【解决方案1】:

供日后参考。从 Git v2.17.0 开始

git status -sb

包含单词 behind 。 因此可以直接用于检查拉动。

注意:记得在运行git status -sb之前运行git fetch

【讨论】:

    【解决方案2】:

    您可以将@987654321@@987654322@ 组合使用。如果git merge-base <branch> <remote branch> 返回的结果与git rev-parse <remote branch> 相同,那么您的本地分支就在前面。如果它返回的结果与git rev-parse <branch> 相同,那么您的本地分支落后了。如果merge-base 返回的答案与rev-parse 不同,则说明分支已经分歧,您需要进行合并。

    不过,最好在检查分支之前先发送git fetch,否则您对是否需要拉取的决定将过时。您还需要验证您检查的每个分支是否都有一个远程跟踪分支。你可以使用@987654323@ --format='%(upstream:short)' refs/heads/<branch> 来做到这一点。该命令将返回<branch> 的远程跟踪分支,如果没有则返回空字符串。 SO上的某个地方有一个不同的版本,如果分支没有远程跟踪分支,它将返回错误,这可能对您的目的更有用。

    【讨论】:

      【解决方案3】:

      最后,我在我的 C++11 git-ws plugin 中实现了这个。

      string currentBranch = run("git rev-parse --abbrev-ref HEAD"); 
      bool canCommit = run("git diff-index --name-only --ignore-submodules HEAD --").empty();
      bool canPush = stoi(run("git rev-list HEAD...origin/" + currentBranch + " --ignore-submodules --count")[0]) > 0;
      

      到目前为止似乎有效。 canPull 仍然需要测试和实现。

      说明:

      • currentBranch 获取控制台输出,是当前分支名称的字符串
      • canCommit 获取控制台是否输出某些东西(当前更改和 HEAD 之间的差异,忽略子模块)
      • canPush 获取 origin/currentBranch 和本地 repo 之间的更改计数 - 如果 > 0,则可以推送本地 repo

      【讨论】:

      • 可以通过git rev-list origin..HEAD为我推送作品
      【解决方案4】:

      来自this answer

      1. 获取:git fetch
      2. 获取当前分支落后了多少次提交:behind_count = $(git rev-list --count HEAD..@{u})
      3. 获取当前分支前面有多少提交:ahead_count = $(git rev-list --count @{u}..HEAD)。 (它假定您从哪里获取是您推送到哪里,请参阅push.default 配置选项)。
      4. 如果behind_countahead_count 均为0,则当前分支是最新的。
      5. 如果behind_count 为0 且ahead_count 大于0,则当前分支在前面。
      6. 如果behind_count 大于0 且ahead_count 为0,则当前分支落后。
      7. 如果behind_countahead_count 都大于0,则当前分支发散。

      解释:

      • git rev-list 列出所有提交范围的提交。 --count 选项输出将列出多少次提交,并禁止所有其他输出。
      • HEAD 命名当前分支。
      • @{u} 指当前分支的本地上游(配置branch.<name>.remotebranch.<name>.merge)。还有@{push},通常与@{u}指向相同。
      • <rev1>..<rev2> 指定提交范围,其中包括可到达的提交,但不包括可到达的提交。如果省略或省略,则默认为 HEAD。

      【讨论】:

        【解决方案5】:

        感谢@Trebor,我只是为了这个目的而拼凑了一个简单的鱼功能:

        #! /usr/bin/fish
        #
        # Echos (to stdout) whether your branch is up-to-date, behind, ahead or diverged from another branch.
        # Don't forget to fetch before calling.
        #
        # @param branch
        # @param otherbranch
        #
        # @echo string up-to-date/behind/ahead/diverged
        #
        # @example
        #
        #   # if master is ahead of origin/master you can find out like this:
        #   #
        #   if test ( branch-status master origin/master ) = ahead
        #
        #      echo "We should push"
        #
        #   end
        #
        function branch-status
        
            set -l a $argv[ 1 ]
            set -l b $argv[ 2 ]
        
            set -l base ( git merge-base $a $b )
            set -l aref ( git rev-parse  $a    )
            set -l bref ( git rev-parse  $b    )
        
                 if [ $aref = $bref ]; echo up-to-date
        
            else if [ $aref = $base ]; echo behind
            else if [ $bref = $base ]; echo ahead
        
            else                     ; echo diverged
            end
        
        end
        

        【讨论】:

        • 谢谢你。到目前为止,在几篇堆栈溢出文章中最清楚的答案。我将其转换为 bash 脚本。
        【解决方案6】:

        我做了一个 bash 版本的 @user1115652 答案。

        function branch_status() {
          local a="master" b="origin/master"
          local base=$( git merge-base $a $b )
          local aref=$( git rev-parse  $a )
          local bref=$( git rev-parse  $b )
        
          if [[ $aref == "$bref" ]]; then
            echo up-to-date
          elif [[ $aref == "$base" ]]; then
            echo behind
          elif [[ $bref == "$base" ]]; then
            echo ahead
          else
            echo diverged
          fi
        }
        

        【讨论】:

          猜你喜欢
          • 2011-05-02
          • 2019-01-21
          • 2012-10-07
          • 2021-07-03
          • 1970-01-01
          • 2011-09-21
          • 2019-01-18
          • 2020-11-05
          • 1970-01-01
          相关资源
          最近更新 更多