git:以编程方式知道分支在远程分支之前/之后的程度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2969214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
git: programmatically know by how much the branch is ahead/behind a remote branch
提问by Olivier Verdier
I would like to extract the information that is printed after a git status
, which looks like:
我想提取在 a 之后打印的信息,git status
如下所示:
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
Of course I can parse the output of git status
but this is not recommended since this human readable output is liable to change.
当然,我可以解析 的输出,git status
但不推荐这样做,因为这个人类可读的输出可能会改变。
There are two problems:
有两个问题:
- How to know the remote tracked branch? It is often
origin/branch
but need not be. - How to get the numbers? How to know whether it is ahead/behind? By how many commits? And what about the diverged branch case?
- 如何知道远程被跟踪的分支?它经常
origin/branch
但不必如此。 - 如何获得数字?如何知道它是否在前面/后面?通过多少次提交?那么分歧的分支案例呢?
采纳答案by araqnid
update
更新
As pointed out by amalloy, recent versions of git support finding the matching tracking branch for a given branch by giving "branchname@{upstream}" (or "branchname@{u}", or "@{u}" for the tracking branch of HEAD). This effectively supercedes the script below. You can do:
正如 amalloy 所指出的,最近版本的 git 支持通过为跟踪分支提供“branchname@{upstream}”(或“branchname@{u}”或“@{u}”)来为给定分支找到匹配的跟踪分支头)。这有效地取代了下面的脚本。你可以做:
git rev-list @{u}..
git rev-list --left-right --boundary @{u}...
gitk @{u}...
etc. For example, I have git q
aliased to git log --pretty='...' @{u}..
to show me "queued" commits ready for pushing.
等等。例如,我使用git q
别名来git log --pretty='...' @{u}..
向我展示准备推送的“排队”提交。
original answer
原答案
There doesn't seem to be an easy way to find the tracking branch in general, without parsing lots more git config than is practical in a few shell commands. But for many cases this will go a long way:
通常似乎没有一种简单的方法可以找到跟踪分支,而无需解析比一些 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
Another, more brute-force, approach:
另一种更暴力的方法:
git rev-list HEAD --not --remotes
jamessan's answer explains how to find the relative differences between $tracking_branch and HEAD using git rev-list
. One fun thing you can do:
jamessan 的回答解释了如何使用git rev-list
. 你可以做的一件有趣的事情:
git rev-list --left-right $tracking_branch...HEAD
(note threedots between $tracking_branch and HEAD). This will show commits on both "arms" with a distinguishing mark at the front: "<" for commits on $tracking_branch, and ">" for commits on HEAD.
(注意$tracking_branch 和 HEAD 之间的三个点)。这将显示两个“臂”上的提交,并在前面带有一个明显的标记:“<”表示 $tracking_branch 上的提交,“>”表示 HEAD 上的提交。
回答by jamessan
git rev-list origin..HEAD
will show the commits that are in your current branch, but not origin -- i.e., whether you're ahead of origin and by which commits.
git rev-list origin..HEAD
将显示您当前分支中的提交,但不显示原点——即,您是否领先于原点以及由哪个提交。
git rev-list HEAD..origin
will show the opposite.
git rev-list HEAD..origin
将显示相反。
If both commands show commits, then you have diverged branches.
如果两个命令都显示提交,那么您就有了分支。
回答by max
You can try git branch -v -v
. With -v
flag given twice, it outputs names of upstream branches. Sample output:
你可以试试git branch -v -v
。与-v
标志给予两次,它输出上游分支的名称。示例输出:
* devel 7a5ff2c [origin/devel: ahead 1] smaller file status overlay icons
master 37ca389 [origin/master] initial project check-in.
I think this format is more stable than git status
output.
我认为这种格式比git status
输出更稳定。
回答by scicalculator
Edit:My original answer was actually not very good because it relied on the user to have a remote called "origin". It also failed if the current branch was had a tracking branch besides origin-head. These flaws essentially made it useless. However, the answer by @araqnid is not the most efficient method and the way he arrives at $tracking_branch
is less than strait forward. The most efficient (fastest) method I have found to get the same functionality is the following:
编辑:我原来的答案实际上不是很好,因为它依赖于用户拥有一个名为“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 and based on left vs. right tracking
# inspired by @adam_spiers
set -- $(git rev-list --left-right --count $tracking_branch...HEAD)
behind=
ahead=
original answer: (inferior, but given for clarity)
原始答案:(较差,但为了清楚起见而给出)
Perhaps the simplest method I could find (inspired by @insidepower)
也许我能找到的最简单的方法(灵感来自@insidepower)
# count the number of logs
behind=$(git log --oneline HEAD..origin | wc -l)
ahead=$( git log --oneline origin..HEAD | wc -l)
I had previously been using the method of @araqnid, but now I think I'll move some of my scripts to this method since it is much simpler. This should work on any unix system.
我之前一直在使用@araqnid 的方法,但现在我想我会将我的一些脚本移到这种方法中,因为它要简单得多。这应该适用于任何 Unix 系统。
回答by Hamish Downer
git status
has a --porcelain
option that is intended for parsing by scripts. It is based on the --short
output - they are almost identical at the time of writing (see the "Porcelain Format" section of the git status man pagefor details). The main difference is that --short
has colour output.
git status
有一个--porcelain
用于由脚本解析的选项。它基于--short
输出 - 在撰写本文时它们几乎相同(有关详细信息,请参阅git status 手册页的“瓷器格式”部分)。主要区别在于--short
具有颜色输出。
By default no branch information is shown, but if you add the --branch
option you will get output like:
默认情况下不显示分支信息,但如果添加该--branch
选项,您将获得如下输出:
git status --short --branch
## master...origin/master [ahead 1]
?? untrackedfile.txt
...
If you are up to date (after a fetch), the branch line will just be:
如果您是最新的(获取后),分支线将是:
## master
If you are ahead:
如果你领先:
## master...origin/master [ahead 1]
If you are behind:
如果你落后:
## master...origin/master [behind 58]
And for both:
对于两者:
## master...origin/master [ahead 1, behind 58]
Note that git status --porcelain --branch
is only available in 1.7.10.3or later (though git status --short --branch
has been available since 1.7.2).
请注意,git status --porcelain --branch
仅在1.7.10.3或更高版本中git status --short --branch
可用(尽管自1.7.2以来可用)。
回答by joeytwiddle
In modern versions of git, @{u}
points to the upstream of the current branch, if one is set.
在现代版本的 git 中@{u}
,如果设置了,则指向当前分支的上游。
So to count how many commits you are behind the remote tracking branch:
因此,要计算您在远程跟踪分支后面的提交次数:
git rev-list HEAD..@{u} | wc -l
And to see how far you are ahead of the remote, just switch the order:
要查看您领先遥控器多远,只需切换顺序:
git rev-list @{u}..HEAD | wc -l
For a more human-readable summary, you could ask for a log instead:
要获得更易读的摘要,您可以要求提供日志:
git log --pretty=oneline @{u}..HEAD
For my own purposes, I am working on a script that will replace @{u}
with an appropriate guess, if no upstream is yet set. Unfortunately there is at this time no @{d}
to represent the downstream (where you would push to).
出于我自己的目的,我正在编写一个脚本@{u}
,如果尚未设置上游,该脚本将替换为适当的猜测。不幸的是,此时没有@{d}
代表下游(您将推向的地方)。
回答by Till
Why wouldn't this work:
为什么这行不通:
#!/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
回答by VonC
How to know the remote tracked branch? It is often
origin/branch
but need not be.
如何知道远程被跟踪的分支?它经常
origin/branch
但不必如此。
Git 2.5+ introduces a new shortcut which references the branch you are pushing to. @{push}
: that would be the remote tracking branch which is of interest here.
Git 2.5+ 引入了一个新的快捷方式,它引用您要推送到的分支。@{push}
:这将是这里感兴趣的远程跟踪分支。
That means you have another option to see ahead/behind for all branches which are configured to push to a branch.
这意味着您有另一个选项可以查看配置为推送到分支的所有分支的前/后。
git for-each-ref --format="%(push:track)" refs/heads
See more at "Viewing Unpushed Git Commits"
在“查看未推送的 Git 提交”中查看更多信息
回答by Adam Spiers
The top chunk of code in araqnid's answer doesn't work for me, so maybe something in git has changed since it was written 18 months ago. It works if I change:
araqnid 的答案中最上面的代码块对我不起作用,所以自 18 个月前编写以来,git 中的某些内容可能已经发生了变化。如果我改变它会起作用:
tracking_branch=refs/remotes/$remote/$remote_branch
to
到
tracking_branch=$remote/$remote_branch
However there is still an issue when tracking a local branch, in which case you have to trim the remote part (which becomes '.'):
但是,在跟踪本地分支时仍然存在问题,在这种情况下,您必须修剪远程部分(变成“.”):
tracking_branch=${tracking_branch#./}
Then you can programmatically obtain the number of revisions behind and ahead as follows:
然后,您可以通过编程方式获取前后修订的数量,如下所示:
set -- `git rev-list --left-right --count $tracking_branch...HEAD`
behind=""
ahead=""
I've written scripts to do all that (and more - e.g. they can also attempt to spot remotes on the other side of a git-svn bridge), and published them in my git-config repository on github. For example, here's my git-compare-upstream. See the READMEfor installation instructions and other handy related scripts.
我已经编写了脚本来完成所有这些(以及更多 - 例如,他们还可以尝试在 git-svn 桥的另一侧发现遥控器),并将它们发布在我的 github 上的 git-config 存储库中。例如,这是我的git-compare-upstream。有关安装说明和其他方便的相关脚本,请参阅自述文件。