Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to see how many commits a local branch is ahead/behind another local branch in git?

Tags:

git

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.

like image 736
timetofly Avatar asked Dec 10 '14 17:12

timetofly


People also ask

How do you check if branch is behind?

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.

How do I find commits between two branches?

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.

What is ahead and behind in git?

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.

How can I see Unpushed commits?

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.


1 Answers

Listing and counting commits: 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 Cs are common commits, Ls 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:

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

  2. Add --count to the git rev-list arguments to make it print a count instead of the raw commit-ID SHA-1 values.

  3. 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}...)

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

like image 122
torek Avatar answered Oct 03 '22 04:10

torek