I can run these commands and get expected output
$ git branch --track test
$ git checkout test
$ touch hello.txt
$ git add hello.txt
$ git commit -m hello.txt
$ git status
On branch test
Your branch is ahead of 'master' by 1 commit.
However here is where my issue is
$ git checkout master
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
I want to know if I am ahead of origin/master
, but I also want to know if I am
behind test
. I am looking for a command to give me something like this:
On branch master
Your branch is up-to-date with 'origin/master'.
Your branch is behind 'test' by 1 commit, and can be fast-forwarded.
There is no such thing built in, and tracking is stored only in the other direction: "X tracks Y", not "Y is tracked by ...", which is more complex as the "..." part can expand to more than one item. (Also, I believe it's much more typical for Y to be a remote-tracking branch in the first place, in which case you can't ever be on Y—though a command that tries to find "what tracks Y" could certainly take arguments, so you could say "tell me about any of my branches that track origin/master
).
That said, it's certainly possible to build such a thing. The algorithm looks like this, in Python-esque pseudo-code:
table = {}
for branch in local_branches:
try:
remote, tracked = get_what_branch_tracks(branch)
except ValueError:
continue # local branch "branch" not tracking anything
try:
br2 = analyze(branch, remote, tracked)
except ValueError:
warn('upstream for %s is gone' % branch)
continue
# at this point br2 is, e.g., origin/master or a local branch that "branch" tracks
table.setdefault(br2, []).append(branch)
# now table[] is a table of branches that are tracked, with
# each table[key] being the branches that track branch "key"
So now for any interesting branch(es) that are in table
, you simply count revisions find-able in the various branch pairs, the same way git status
does, which in shell is just:
# to compute "git status" for branch X that tracks Y:
nahead=$(git rev-list --count Y..X) # we're ahead $nahead commits
nbehind=$(git rev-list --count X..Y) # and behind $nbehind
If you're behind but not ahead, you can fast-forward.
The details for get_what_branch_tracks
are simply to do some git config --get
s, of branch.branch.remote
and of branch.branch.merge
, while the details for analyze
are more complex: if remote
is .
then whatever is in tracked
is simple, but if it's an actual remote, whatever is in tracked
must be passed through the corresponding fetch
lines to find the appropriate remote-tracking branch.