git: programmatically know by how much the branch is ahead/behind a remote branch
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 HEAD..origin
will show the opposite.
If both commands show commits, then you have diverged branches.
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:
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.
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:
# 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:
git rev-list --left-right $tracking_branch...HEAD
(note three dots 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.
You can try git branch -v -v
. With -v
flag given twice, it outputs names of upstream branches. Sample output:
* 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.