If I'm working on a feature branch, I would like to know how many commits this branch is ahead or behind the master branch. I can't seem to find the command that does this.
You can do this with a combination of git merge-base and git rev-parse . If git merge-base <branch> <remote branch> returns the same as git rev-parse <remote branch> , then your local branch is ahead. If it returns the same as git rev-parse <branch> , then your local branch is behind.
In order to see the commit differences between two branches, use the “git log” command and specify the branches that you want to compare. Note that this command won't show you the actual file differences between the two branches but only the commits.
branch is X commits behind means that there are X new (unmerged) commits on the branch which is being tracked by your current branch. branch is X commits ahead analogously means that your branch has X new commits, which haven't been merged into the tracked branch yet.
We can view the unpushed git commits using the git command. It will display all the commits that are made locally but not pushed to the remote git repository.
git rev-list
A quick way is to do what git status
does when there's an "upstream". Specifically, git status
simply counts revisions that are on the current branch that are not on the upstream branch. For instance, consider branch foo
that has an upstream of origin/foo
, and suppose you've made three local commits and then used git fetch
to bring in one upstream commit:
L - L - L <-- foo
/
... - C - C
\
U <-- origin/foo
Here C
s are common commits, L
s are local commits, and U
is an upstream commit. If you're on branch foo
and you run git status
you'll see "ahead 3, behind 1".
Here's how git gets those numbers:
git rev-list foo --not origin/foo
: this produces a list of all commits on foo
but not on origin/foo
. That is, starting at origin/foo
(which is commit U
), strike out the commit and all earlier commits reachable: that's U
and all the C
commits. Then, start at foo
and find all reachable commits that are not already struck out: that's just the three L
commits.
Add --count
to the git rev-list
arguments to make it print a count instead of the raw commit-ID SHA-1 values.
Repeat for git rev-list origin/foo --not foo
: this is all commits that are reachable from origin/foo
but not from foo
, which in this example is just commit U
. (Again, add --count
to get just the count, rather than the actual commit IDs.)
Note that foo --not origin/foo
is also spelled origin/foo..foo
in gitrevisions syntax. (In the case of git status
it's always looking at the current branch—which is named via HEAD
—and its upstream. You can use the @{upstream}
syntax to obtain the name of the upstream, or shorten this to @{u}
; and HEAD
is the default if you list no name at all; so to re-implement git status
you can just look at git rev-list --count ..@{u}
and git rev-list --count @{u}..
.)
rev-list
on local branches, vs using git cherry
Hence, if you want to count commits reachable from branch feature
but not from branch master
, you can do the same thing but with the names feature
and master
. The git rev-list
syntax master..feature
names all commit IDs reachable from feature
but not from master
, and --count
will get you a count:
git rev-list --count master..feature
If you've cherry-picked some commits from one branch to another, though, so that they have different commit IDs but the same diff, this will "over-count". For instance suppose feature
had five commits that master
did't, but then you (or someone) had decided that one of those five commits should be cherry-picked into master
, you might now have this:
D - E - F - G - H <-- feature
/
... - C - C
\
F' <-- master
where F'
is basically just a copy of commit F
. If you ask git rev-list
to count commits on feature
that are not on master
, you'll get 5; but if you ask git cherry
to find commits on feature
that are not on master
, it will eliminate commit F
from its list, because it will see that F'
is a copy of F
. If you count the commits listed by git cherry
you will therefore get 4, not 5.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With