检查本地git repo是否领先/落后于远程

问题描述 投票:0回答:7

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

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

  • 可以承诺吗?

    如果

    git diff-index --name-only --ignore-submodules HEAD --
    返回某些内容, 那么是的,有需要提交的更改。

  • 可以推吗?

    如果

    git status -sb
    在其输出中包含单词 ahead,那么是的,有 正在致力于推动。

  • 可以拉吗?

    尚未实施任何措施。

可以提交?部分似乎工作正常。 可以推送吗?只适用于master分支,这是一个很大的问题。

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

git pull

linux git bash shell github
7个回答
33
投票

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

git status -sb

包含单词behind。 这样就可以直接用来检查拉动情况。

注意:运行

git fetch
之前记得先运行
git status -sb


23
投票

来自这个答案

  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_count
    ahead_count
    都为 0,则当前分支是最新的。
  5. 如果
    behind_count
    为 0 并且
    ahead_count
    大于 0,则当前分支位于前面。
  6. 如果
    behind_count
    大于0且
    ahead_count
    为0,则当前分支落后。
  7. 如果
    behind_count
    ahead_count
    都大于0,则当前分支分叉。

说明:

  • git rev-list
    列出给定提交范围的所有提交。
    --count
    选项输出将列出多少提交,并抑制所有其他输出。
  • HEAD
    命名当前分支。
  • @{u}
    指当前分支的本地上游(由
    branch.<name>.remote
    branch.<name>.merge
    配置)。还有
    @{push}
    ,通常与
    @{u}
    指向相同。
  • <rev1>..<rev2>
    指定提交范围,其中包括可从 访问的提交,但排除可从 访问的提交。当 或 被省略时,它默认为 HEAD。

10
投票

您可以结合使用

git merge-base
git rev-parse
来完成此操作。如果
git merge-base <branch> <remote branch>
返回与
git rev-parse <remote branch>
相同,则您的本地分支领先。如果它返回与
git rev-parse <branch>
相同,那么你的本地分支落后了。如果
merge-base
返回的答案与
rev-parse
不同,则分支已分叉,您需要进行合并。

不过,最好在检查分支之前先做一下

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


7
投票

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

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
    和本地仓库之间的更改计数 - 如果
    > 0
    ,则可以推送本地仓库

7
投票

我制作了 @user1115652 答案的 bash 版本。

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
}

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

0
投票

我认为这应该在 git 包中配备,例如 'git status -c' 来与远程仓库进行比较,无论它是领先还是落后。

© www.soinside.com 2019 - 2024. All rights reserved.