Git: programmatically know how far the branch is ahead / behind the remote branch

I would like to extract the information printed after git status , which looks like this:

 # 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, as this human-readable output may change.

There are two problems:

  • How to know the remote remote branch? This is often origin/branch , but not required.
  • How to get numbers? How to find out ahead? How much commit? What about the case of divergent branching?
+41
git git-status
Jun 03 '10 at 19:43
source share
9 answers

Update

As noted by amalloy, recent git versions support the search for the appropriate tracking branch for a given branch, providing "branchname @ {upstream}" (or "branchname @ {u}" or "@ {u}" for the HEAD tracking branch). This effectively undoes the script below. You can do:

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

etc .. For example, I have git q with the alias git log --pretty='...' @{u}.. to show that I have "queued", ready to click.

original answer

There seems to be no easy way to find the tracking branch at all, without parsing more git config than is practical in several shell commands. But for many cases this will go a long way:

 # 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, rougher 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:

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

(note the three points between $ tracking_branch and HEAD). This will show the commit on both β€œshoulders” with a distinctive front sign: β€œ<” for commit on $ tracking_branch and β€œ>” for commit on HEAD.

+17
Jun 03 '10 at 22:01
source share

git rev-list origin..HEAD will show the commits that are in your current branch, but not the origin - that is, will you exceed the beginning for some reason.

git rev-list HEAD..origin will show the opposite.

If both commands show commits, then you have diverging branches.

+19
Jun 03 '10 at 20:08
source share

You can try git branch -v -v . If the -v flag is specified twice, it displays the branch names upstream. Output Example:

 * 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 .

+10
04 Jun. '10 at 2:59 a.m.
source share

Edit: My initial answer was actually not very good, because it relied on the user to have a remote origin call. It also failed if the current branch had a tracking branch other than the initial one. These flaws essentially made it useless. However, @araqnid's answer is not the most efficient method, and the way it reaches $tracking_branch is less than a breakthrough ahead. The most efficient (fastest) method I found to get the same functionality is the following:

 # 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 



original answer: (bottom, but given for clarity)

Perhaps the easiest way I could find (inspired by @insidepower)

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

I used the @araqnid method earlier, but now I think that I will transfer some of my scripts to this method, since it is much simpler. This should work on any unix system.

+6
Nov 01 '12 at 6:52
source share

git status has the --porcelain option for script parsing. It is based on the output of --short - they are almost identical at the time of writing (see the section "Porcelain format" on the git status page). The main difference is that --short has a color output.

By default, branch information is not displayed, but if you add the --branch option, you will get output, for example:

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

If you are out of date (after fetching), the branch line will only:

 ## 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] 

Please note that git status --porcelain --branch is only available in 1.7.10.3 or later (although git status --short --branch is available from 1.7.2 ).

+4
Aug 19 '13 at 14:40
source share

In modern versions of git, @{u} points to the top of the current branch, if installed.

So, to calculate how many delays you are behind the remote tracking branch:

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

And to see how far you are from the remote, just switch the order:

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

For a more readable summary, you can request a journal instead:

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

For my own purposes, I am working on a script that will replace @{u} with the corresponding hunch if the upstream is not already installed. Unfortunately, at this time there is no @{d} to represent the downstream (where you click).

+4
Dec 13 '13 at 9:19
source share

The top of the code in the araqnid answer does not work for me, so maybe something in git has changed since it was written 18 months ago. It works if I change:

 tracking_branch=refs/remotes/$remote/$remote_branch 

to

 tracking_branch=$remote/$remote_branch 

However, there is still a problem tracking the local branch, in which case you need to trim the remote part (which becomes "."):

 tracking_branch=${tracking_branch#./} 

Then you can programmatically get the number of revisions back and forth as follows:

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

I wrote scripts to do all this (and much more - for example, they can also try to find remote objects on the other side of the git-svn bridge) and publish them to my git -config repository on github . For example, here is git-compare-upstream . See README for installation instructions and other handy scripts.

+1
Nov 28 '11 at 10:19
source share

Why not 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 
+1
Jun 04 2018-12-12T00:
source share

How to know the remote remote branch? This is often origin/branch , but not required.

Git 2.5+ introduces a new shortcut that links to the branch you click on. @{push} : this will be the remote tracking branch that is of interest here.

This means that you have another way to see forward / backward for all branches that are configured to click on a branch.

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

For more information, see Viewing Unpushed Git Commits. "

+1
Jun 08 '15 at 22:53
source share



All Articles