检查本地git repo是否位于远程前后

时间:2013-07-18 09:39:48

标签: linux git bash shell github

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

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

  • 可以提交吗?

    如果git diff-index --name-only --ignore-submodules HEAD --返回某些内容, 然后是的,有提交的更改。

  • 可以推送吗?

    如果git status -sb在其输出中包含提前这个词,那么是的,那里 承诺推动。

  • 能拉吗?

    尚未实施。

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

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

6 个答案:

答案 0 :(得分:5)

您可以git merge-basegit 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的某个地方有一个不同的版本,如果分支没有远程跟踪分支,它将返回错误,这可能对您的目的更有用。

答案 1 :(得分:4)

最后,我在我的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获取原点/ currentBranch与本地仓库之间的更改计数 - 如果> 0,则可以推送本地仓库

答案 2 :(得分:1)

感谢@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

答案 3 :(得分:1)

供将来参考。截至Git v2.17.0

git status -sb

包含背后的单词。 这样可以直接用来检查拉力。

注意:请务必在运行git fetch

之前运行git status -sb

答案 4 :(得分:1)

我制作了@ 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 :(得分:1)

来自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。