【问题标题】:git: programmatically know by how much the branch is ahead/behind a remote branchgit:以编程方式知道分支在远程分支前面/后面的距离
【发布时间】:2011-02-27 11:49:59
【问题描述】:

我想提取在git status 之后打印的信息,如下所示:

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

我当然可以解析git status 的输出,但不建议这样做,因为这个人类可读的输出可能会发生变化。

有两个问题:

  1. 如何知道远程被跟踪的分支?通常是origin/branch,但不一定是。
  2. 如何获取数字?如何知道它是否领先/落后?通过多少次提交?那么分歧分支案例呢?

【问题讨论】:

标签: git git-status


【解决方案1】:

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

git rev-list HEAD..origin 将显示相反的内容。

如果两个命令都显示提交,那么你有分歧的分支。

【讨论】:

  • 谢谢,rev-list 似乎按预期工作,但branch -r 没有准确地提供远程跟踪分支。我没有你写的origin/HEAD,但是有一个远程跟踪的分支,我可以用rev-list得到提交的数量。
  • 嗯,branch -r 似乎没有像我想的那样做。已更新。
【解决方案2】:

更新

正如 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 的回答解释了如何使用git rev-list 找到 $tracking_branch 和 HEAD 之间的相对差异。你可以做一件有趣的事:

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

(注意 $tracking_branch 和 HEAD 之间的 三个 点)。这将显示两个“臂”上的提交,前面有一个区别标记:“”表示 HEAD 上的提交。

【讨论】:

  • 好极了! --left-right 的三个点绝对是对 jamessan 答案的改进。对于遥控器,我想唯一可靠的方法是,正如你所建议的,阅读 git config...
  • 对我不起作用 - 请参阅 my answer below。
  • @{u} 不是您正在跟踪的分支的当前 SHA 吗?我认为你的整个脚本可以用git rev-list @{u}..HEAD 替换在 git 的中途版本(即,不是四年前)。
  • @amalloy 是的,似乎是这样。不知道什么时候添加的,谢谢指出!
【解决方案3】:

你可以试试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输出更稳定。

【讨论】:

  • git status 具有提供稳定输出的--porcelain 标志,但它不显示前/后信息。
  • 太棒了!我从来没有注意到这个带有 git branch 的双重选项......有一个带有双重选项的命令是很不寻常的,不是吗?感谢您的提示
  • 这看起来很简单。我会用这个。
  • @OlivierVerdier:不,这并不是你完全没有听说过的。您可能只是将其视为-vv 而不是-v -v。您偶尔会看到它提供不同级别的详细输出,而无需为每个级别添加不同的标志。
  • @jamessan - 你可以使用--porcelain --branch 来查看前面/后面的信息(虽然你需要一个相当新的 git 版本,但它不在 1.7.9(ubuntu 12.04)中,但是在 1.8.3 中)。 --short --branch 现在几乎相同,在 1.7.9 中可用
【解决方案4】:

在现代版本的 git 中,@{u} 指向当前分支的上游(如果已设置)。

所以要计算你在远程跟踪分支后面有多少次提交:

git rev-list --count HEAD..@{u}

要查看您领先遥控器多远,只需切换顺序即可:

git rev-list --count @{u}..HEAD

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

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

出于我自己的目的,我正在编写一个脚本,如果尚未设置上游,则该脚本将用适当的猜测替换 @{u}。不幸的是,目前没有@{d} 代表下游(您将推送到的地方)。

【讨论】:

    【解决方案5】:

    编辑: 我最初的答案实际上不是很好,因为它依赖于用户拥有一个名为“origin”的遥控器。如果当前分支除了 origin-head 之外还有一个跟踪分支,它也会失败。这些缺陷基本上使它毫无用处。但是,@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 系统。

    【讨论】:

    • --count 选项是何时添加到 got rev-list 的?我正在使用的git 1.7.1 中似乎不存在它。
    • 我不确定它是在哪个版本中引入的,但自从我一年多前开始使用 git 以来,它就一直存在。邮件列表“PATCH rev-list --count: separate count for --cherry-mark”(v1.7.5) 上的这封电子邮件表明它早在 2011 年 4 月就可以使用。
    • 叹息。可悲的是,在企业环境中使用支持的 Linux(如 RHEL6)的缺点之一是不得不与一些相对快速移动的软件(如git)的可悲旧版本作斗争。做了一些研究后,看起来在 1.7.1 和 1.7.6 之间的 git 中添加了 很多 有用的功能。不幸的是,我找不到git 的页面,该页面相当于hg 的WhatsNew 页面。
    • 只是添加到原始答案中,您可以使用:remote="$(git config --get branch.${branch}.remote 2>/dev/null)" 获取来源名称,然后您也可以使用原始答案中的版本。
    【解决方案6】:

    git status 有一个 --porcelain 选项,用于通过脚本进行解析。它基于--short 输出 - 在撰写本文时它们几乎相同(有关详细信息,请参阅git status man page 的“瓷器格式”部分)。主要区别在于--short有颜色输出。

    默认情况下不显示分支信息,但如果添加--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 开始可用)。

    【讨论】:

    • --short 有颜色,--porcelain 没有颜色
    【解决方案7】:

    为什么这不起作用:

    #!/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 
    

    【讨论】:

    • 这行不通,因为我想知道 repo 在遥控器的前面/后面有多少。反正这个问题已经有了很好的答案。
    • 我认为,RETVAL 将是它领先的提交数量。我不确定它是否适用于“后面”(例如需要拉)。
    【解决方案8】:

    araqnid 答案中的最上面的代码块对我不起作用,所以 git 中的某些内容可能自 18 个月前编写以来发生了变化。如果我改变它会起作用:

    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】:

      如何知道远程跟踪的分支?通常是origin/branch,但不一定是。

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

      这意味着您有另一个选项可以查看配置为推送到分支的所有分支的前方/后方。

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

      在“Viewing Unpushed Git Commits”查看更多信息

      【讨论】:

      【解决方案10】:

      你应该使用最新版本的 git

      git status --porcelain --branch
      

      并检查前后:

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

      --瓷器[=版本]

      以易于解析的格式为脚本提供输出。这类似于 short 输出,但在 Git 版本中将保持稳定,无论 用户配置。详情见下文。

      -b,--分支

      即使以短格式显示分支和跟踪信息。

      【讨论】:

        猜你喜欢
        • 2018-09-25
        • 2020-04-04
        • 2012-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-02
        • 2013-03-19
        • 1970-01-01
        相关资源
        最近更新 更多