Skip to the content.

Compare commits between 2 branches

IMO, the ideal tool showing the different commits between 2 branches need to

  1. list all the different commits E, D, B;
  2. mark the direction (which branch has the commit);
  3. have the output format which is highly readable and is even customizable.

Sometimes we want to know the symmetric difference in manner of commits NOT code lines of 2 branches before merging them. I noticed that there are some ways to do this but most of them are not ideal to me.

Here I list some ways and my comments. And provide my approach to do this. (Use my experimental repo as demo). The commits and the branches graph look like below:

A ------ C ------ E (branch:main)
 \       |
  ·- B - C -- D (branch:feat)

Fig 1

IMO, the ideal tool showing the different commits between 2 branches need to

  1. list all the different commits E, D, B;
  2. mark the direction (which branch has the commit);
  3. have the output format which is highly readable and is even customizable.

1. git log

git log branch1..branch2 or git log branch1...branch2

Or an one-line way: git log --oneline branch1...branch2

Use git-log can list the commits on one branch and not on another branch. This is what exact we need. The parts I don’t like are:

  • If use double-dots, it only shows the incremental commits on the right-hand branch compared with the common ancestor, but not with the left-hand branch: image

  • If use triple-dots, it does show all different commits but you cannot tell which branch does the different commit come from: image

2. git show-branch

git show-branch branch1 branch2

git-show-branch is another very useful tool to list commits. The problem is it stops at the first common commit appearing at the 2 branches both.

image
The fig shows by default git-show-branch stops at commit [main^] Commit on main., which is commit C in fig1

To show more commits, an option --more=x need to be passed in but actually we are not able to know what’s a suitable value of x.

image
The fig shows the expected result of all the 3 different commits but –more=5 is not always working

3. git rev-list

git rev-list --oneline --left-right main...feat

image

This is almost the exptected one, if not considering the output formats. If we want to customize the format (like adding commiter name, date), the output can be a little bit messy to me:

image
A sample using --pretty=reference
image
Another sample using customized formats

Anyway it’s already good enough to show the different commits, and we could use sed or other tools to make the output more readable. In newer version of git, git-rev-list provides option no-commit-header with which the output can be cleaner.

4. a shell script or function

If we want everything under our control, the best way is to write a shell script. I borrow the idea from Kim Briggs on Stackoverflow and add more customization in git log and diff part:

# Function to retrieve different commits between branches:
function gitbd() {
  if ((2==$#)); then
    alog=/tmp/gitbd_$(echo $1 | tr '/' '-').log
    blog=/tmp/gitbd_$(echo $2 | tr '/' '-').log
    git log --pretty="format:%h %as %s (%cn)" $1 > $alog
    git log --pretty="format:%h %as %s (%cn)" $2 > $blog
    colordiff -u $alog $blog | less
    # vi -d $alog $blog
    # diff -u $alog $blog
    rm $alog $blog
  fi
}

Add the function in your shell rc, then in command line, gitbd main feat will give the different commits list, and colored in a very git way, also shows the common commits around the different ones:

image

The format of each line can be customized by modifying git log part of the function. The diff utility can be replaced with anything else you like. Currently this function requires colordiff, but you could choose vim or just diff if your diff supports --color.

image
Vim diff

END

Written on August 29, 2022