代码之家  ›  专栏  ›  技术社区  ›  Olivier Verdier

Git:通过编程知道远程分支前面/后面有多少分支

  •  43
  • Olivier Verdier  · 技术社区  · 15 年前

    我想提取在 git status ,看起来像:

    # On branch master
    # Your branch is ahead of 'origin/master' by 2 commits.
    

    当然,我可以解析 GIT状态 但不建议这样做,因为这种人类可读的输出很容易改变。

    有两个问题:

    1. 如何知道远程跟踪分支?它经常是 origin/branch 但不必。
    2. 如何获取数字?如何知道它是在前面还是在后面?通过多少承诺?那分歧的分支案例呢?
    9 回复  |  直到 9 年前
        1
  •  17
  •   pradyunsg ThisIsAQuestion    11 年前

    更新

    正如Amalloy所指出的,Git的最新版本支持通过给“branchname@upstream”(或“branchname@u”,或“@u”(用于head的跟踪分支)查找给定分支的匹配跟踪分支。这实际上取代了下面的脚本。你可以做到:

    git rev-list @{u}..
    git rev-list --left-right --boundary @{u}...
    gitk @{u}...
    

    例如,我有 git q 别名 git log --pretty='...' @{u}.. 显示“排队”提交准备推送。

    原始答案

    一般来说,要找到跟踪分支似乎不是一个简单的方法,不需要解析比几个shell命令实际更多的git-config。但在许多情况下,这将有很长的路要走:

    # work out the current branch name
    currentbranch=$(expr $(git symbolic-ref HEAD) : 'refs/heads/\(.*\)')
    [ -n "$currentbranch" ] || die "You don't seem to be on a branch"
    # look up this branch in the configuration
    remote=$(git config branch.$currentbranch.remote)
    remote_ref=$(git config branch.$currentbranch.merge)
    # convert the remote ref into the tracking ref... this is a hack
    remote_branch=$(expr $remote_ref : 'refs/heads/\(.*\)')
    tracking_branch=refs/remotes/$remote/$remote_branch
    # now $tracking_branch should be the local ref tracking HEAD
    git rev-list $tracking_branch..HEAD
    

    另一种更野蛮的方法:

    git rev-list HEAD --not --remotes
    

    Jamessan的答案解释了如何找到$tracking ou branch和head using之间的相对差异。 git rev-list . 你可以做一件有趣的事:

    git rev-list --left-right $tracking_branch...HEAD
    

    (音符 $tracking ou branch和head之间的点)。这将显示两个“ARM”上的提交,前面有一个区别标记:“<”用于$tracking_分支的提交,而“>”用于头上的提交。

        2
  •  22
  •   jamessan    15 年前

    git rev-list origin..HEAD 将显示当前分支中的提交,但不显示源——即,您是否领先于源,以及提交的依据。

    git rev-list HEAD..origin 会显示相反。

    如果两个命令都显示提交,那么您就有了不同的分支。

        3
  •  11
  •   max    15 年前

    你可以试试 git branch -v -v . 用 -v 标志给出两次,它输出上游分支的名称。样品输出:

    * devel  7a5ff2c [origin/devel: ahead 1] smaller file status overlay icons
      master 37ca389 [origin/master] initial project check-in.
    

    我认为这种格式比 git status 输出。

        4
  •  7
  •   scicalculator    12 年前

    编辑: 我的原始答案实际上不是很好,因为它依赖于用户有一个称为“来源”的远程设备。如果当前分支除了原点之外还有一个跟踪分支,那么它也会失败。这些缺陷基本上使它无用。然而,@araqnid的答案并不是最有效的方法,也不是他到达目的地的方式。 $tracking_branch 小于海峡前进。我发现获得相同功能最有效(最快)的方法是:

    # get the tracking-branch name
    tracking_branch=$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))
    # creates global variables $1 and $2 based on left vs. right tracking
    # inspired by @adam_spiers
    set -- $(git rev-list --left-right --count $tracking_branch...HEAD)
    behind=$1
    ahead=$2
    

    原始答案:(次,但为了清楚起见)

    也许是我能找到的最简单的方法(灵感来自@insidepower)

    # count the number of logs
    behind=$(git log --oneline HEAD..origin | wc -l)
    ahead=$( git log --oneline origin..HEAD | wc -l)
    

    我以前使用过@araqnid的方法,但现在我想我将把一些脚本移到这个方法,因为它要简单得多。这可以在任何UNIX系统上工作。

        5
  •  5
  •   joeytwiddle    11 年前

    在Git的现代版本中, @{u} 如果设置了分支,则指向当前分支的上游。

    因此,要计算远程跟踪分支后面有多少提交:

    git rev-list HEAD..@{u} | wc -l
    

    要查看遥控器的领先程度,只需切换顺序:

    git rev-list @{u}..HEAD | wc -l
    

    要获得更易于阅读的摘要,您可以要求输入日志:

    git log --pretty=oneline @{u}..HEAD
    

    为了我自己的目的,我正在编写一个将替换 @ {U} 如果还没有设置上游,则进行适当的猜测。不幸的是,现在没有 @{d} 代表下游(你将推动到哪里)。

        6
  •  5
  •   Hamish Downer JKP    9 年前

    git status 有一个 --porcelain 用于按脚本分析的选项。它是基于 --short 输出-它们在书写时几乎相同(参见 git status man page 详情请参阅。主要区别在于 --短 有颜色输出。

    默认情况下,不显示分支信息,但如果添加 --branch 选项您将得到如下输出:

    git status --short --branch
    ## master...origin/master [ahead 1]
    ?? untrackedfile.txt
    ...
    

    如果您是最新的(在提取之后),分支行将只是:

    ## master
    

    如果你在前面:

    ## master...origin/master [ahead 1]
    

    如果你落后了:

    ## master...origin/master [behind 58]
    

    两者兼而有之:

    ## master...origin/master [ahead 1, behind 58]
    

    注意 git status --porcelain --branch 仅在中可用 1.7.10.3 或者以后(尽管 git status --short --branch 从那以后就有了 1.7.2 )

        7
  •  2
  •   Till    13 年前

    为什么这样不行:

    #!/bin/sh
    git diff origin/master..HEAD --quiet --exit-code
    RETVAL=$?
    if [ $RETVAL -gt 0 ]; then
        echo "You need to git push!"
    else
        echo "No git push necessary!"
    fi 
    
        8
  •  1
  •   Adam Spiers    13 年前

    Araqnid的答案中最重要的部分代码对我来说不起作用,所以也许自18个月前Git编写以来,它的某些内容已经发生了变化。如果我改变了,它就会工作:

    tracking_branch=refs/remotes/$remote/$remote_branch
    

    tracking_branch=$remote/$remote_branch
    

    但是,在跟踪本地分支时仍然存在一个问题,在这种情况下,您必须修剪远程部分(它变为“.”):

    tracking_branch=${tracking_branch#./}
    

    然后,您可以通过编程方式获得前后的修订数量,如下所示:

    set -- `git rev-list --left-right --count $tracking_branch...HEAD`
    behind="$1"
    ahead="$2"
    

    我已经编写了脚本来完成所有这些工作(而且更多-例如,他们还可以尝试在Git SVN桥的另一侧发现远程设备),并将它们发布到 my git-config repository on github . 例如,这是我的 git-compare-upstream . 见 the README 用于安装说明和其他方便的相关脚本。

        9
  •  1
  •   Community CDub    8 年前

    如何知道远程跟踪分支?它经常是 origin/branch 但不必。

    Git2.5+引入了一个新的快捷方式,它引用了您要推到的分支。 @{push} :这将是这里感兴趣的远程跟踪分支。

    这意味着对于配置为推送到分支的所有分支,您有另一个选项来查看前面/后面。

    git for-each-ref --format="%(push:track)" refs/heads
    

    “看更多” Viewing Unpushed Git Commits