What if you wanted to see all the revisions since a branch was created? Or all the changes included in two or more branches? Or all the changes in one branch, that has merges from another branch, but not the merges or the other branch? All of this and more can be done with git rev-parse, which is used by just about every git command that accepts a revision list.

I will use the diagram from the git-rev-parse man page (see the references at the bottom of this post):

     G   H   I   J
      \ /     \ /
       D   E   F
        \  |  / \ 
         \ | /   |
          \|/    |
           B     C
            \   /
             \ /
              A

(The most recent commit in this diagram is A. A is a merge commit between B and C.)

A repo with this sort of history is available here: http://xennet.org/git-rev-parse-example.tar.bz2

Everyone knows about the J^, F^1, and I~4 notation, but they’re less likely to know about the D..B, B…C, and ^J C notations. The former are different ways to refer to a single revision and the latter are ways to refer to ranges of revisions.

The r1..r2 and ^r2 r1 syntaxes are actually the same. They both mean all the commits reachable by r1 but not r2. The second syntax is slightly more powerful because you can say things like ^D ^F B. In our example above (D..B) those commits are E I J F B.

The r1…r2 syntax represents the symmetric difference. In other words, this is all the commits in r1 and r2 but not in both r1 and r2. This is all the commits that will be merged together if the two branches are merged. In our example above (B…C) those commits are G H D E B C.

If you were an integrator and wanted to review a contributor’s branch, and that contributor, during the course of development, merged from master a couple of times, how would you be able to find the commits that were only available in the contributor’s branch (contrib) and not in master? You could easily git log --no-merges ^master contrib (you need the –no-merges because the patches that merge master into contrib aren’t included in master). Using a GUI like tig (tig --no-merges ^master contrib), gitk, or qgit makes it trivially simple to inspect each of the diffs before integrating.

References:

Advertisements