Posted on

Cleaner Git Log With Merges

In some of our repositories now, Panhandler in particular, there are a lot of merge commits.  As the master branch containing the API definition gets updated, each driver branch merges in master so that it can be updated to target the latest API.  This results in the driver branches having various merge commits that bring in master, and that can make the output of a simple ‘git log’ more verbose than you may want.

One useful option for git-log is ‘–no-merges’, which will omit any merge commits.  If we have a repo like this

O---O---A---B---C---D---E---F    [master]
         \           \
  O---O---G---H---I---J---K      [driver]

and we run
$ git checkout driver
$ git log --no-merges
then we won’t see commits G or J, since those are points where master was merged into the driver branch.

But one issue is that we will still see the commits from the master branch.  That can be annoying if all we want to see are the driver commits.  So what we can do is tell Git that we want to exclude them, like so:
$ git log driver ^master
This should be read as, “Display all commits in ‘driver’ that are not in ‘master’”.  Which in this case shows all of the driver branch.

You have probably used the ‘..’ syntax before, writing something like
$ git log driver..origin/driver
to see all of the commits in the ‘origin/driver’ that are not in ‘driver’.  That ‘..’ syntax is actually a short-cut for the first example.  It is entirely equivalent to
$ git log ^driver origin/driver
“All of the commits which are not in ‘driver’ but that are in ‘origin/driver’”.

There are a lot of options for controlling which commits are displayed by git-log.  Ultimately those options stem from git-rev-list, which is the plumbing command used by git-log and many other parts of Git to produce a list of commits.  The documentation for git-rev-list has all the details about ‘History Simplification’, which can help you narrow down your focus when working in a repository that has a lot of merges.