Let us suppose we’ve got the following commit/branch history:
B---C-----D---E-- / \ \ A---F---G--+----H---+--I
Here, the series of commits
B-C-D-E happened on a topic branch that was created when commit
A was the tip (or HEAD, in git-speak) of the master branch. The master branch continued with commits
G – when a remerge had to occur. After another commit
H on top the master branch we got the final merge with the topic branch and another commit
In this scenario, reviewing the series of commits
B-C-D-E plus the merge would be a piece of cake but what happens if
F-G-H-I was forming the topic branch with master getting merged in from time to time? We’d have to tell apart commits, i.e. know not to review
F-G-H as well. It might seem trivial here but figure
F-G-H was really hundreds of commits with even more merges in between.
In this case, rev-list offers the inconspicuous (or even misleadingly
Follow only the first parent commit upon seeing a merge commit. This
option can give a better overview when viewing the evolution of a
particular topic branch, because merges into a topic branch tend to be
only about adjusting to updated upstream from time to time, and this
option allows you to ignore the individual commits brought in to your
history by such a merge.
Creating the review patch
To cut a long story short,
git rev-list --first-parent --reverse HASH-OF-A...HASH-OF-I
does just what you need and prints the series of hashes for
git rev-list --first-parent --reverse HASH-OF-A...HASH-OF-E
B-C-D-E so it even works for a simple use case without in-between merges. Adding
--no-merges will additionally skip the merge commits (+).
Make this an alias in your
~/.gitconfig by adding this:
[alias] review-branch = rev-list --reverse --first-parent
Now, in order to use this for a review, all that’s left to do is using such a list of hashes to retrieve their diffs:
git show $(git review-branch HASH-OF-A...HASH-OF-I) > review.patch
git review-branch HASH-OF-A...HASH-OF-I \ | xargs -n1 git show > review.patch
In order to just get all files involved throughout all commits, you could add some funny action, e.g.
git show $(git review-branch HASH-OF-A...HASH-OF-I) \ | grep -E '^(--- a|\+\+\+ b)/' \ | perl -ple '$_ =~ s/.......*)/$1/' \ | sort | uniq > files
Reviewing the changes
Review Board uses patch files as its native format and even supports loading missing context code from the repository, if set up to do so.
Git kicks ass and I’ve got Balls of Steel™.