Revisions and ranges¶
Understanding revisions and ranges is essential as many git commands take them as arguments.
Depending on the command, revisions denote a specific commit or, for commands which walk the revision graph … all commits which are reachable from that commit.
The example below is based on a repository due to Jon Loeliger (from the above man page). For convenience, with every commit we associate a branch whose name is the same as the (one-letter) commit message. Having branches is convenient as their names can be used to express revisions and ranges succinctly.
Revisions¶
The first two tabs below depict our example repository without and with branches (local
branches can be visualized by passing the -l
flag). The third tab includes
annotations (each one is passed using the -a
flag) with example uses of the caret
(^
) and tilde (~
) symbols:
<rev>~<n>
: then
-th generation ancestor of<rev>
, following only the first parents<rev>^<n>
: then
-th parent of<rev>
.
There are other ways to specify revisions. Some of them are shown in the last tab.
git dag -m 1
git dag -m 1 -l
git dag -m 1 -a A^0 -a A^ -a A^1 -a A~1 -a A^2 -a A^^ -a A^1^1 -a A~2 -a B^2 -a A^^2 -a B^3 -a A^^3 -a A^^^ -a A^1^1^1 -a A~3 -a D^2 -a B^^2 -a A^^^2 -a A~2^2 -a F^ -a B^3^ -a A^^3^ -a F^2 -a B^3^2 -a A^^3^2
git dag -m 1 -a C^{commit} -a HEAD -a :/H -a HEAD^{/F} -a @
Ranges¶
History traversing commands such as git log operate on a set of commits, not just a single commit.
Below we give examples with four ways to define such a set:
<rev>
: commits reachable from<rev>
<rev1> <rev2>
: union of commits reachable from<rev1>
and<rev2>
, etc.
<rev1>..<rev2>
: commits reachable from<rev2>
but not from<rev1>
<rev1>...<rev2>
: commits reachable from either<rev1>
or<rev2>
but not from both<rev>^@
: all (direct/indirect) parents of<rev>
.
In addition, the last two tabs depict the effect of using --ancestry-path
in
combination with a range [1]. For example, range D..A
includes all reachable
commits from A
that are not reachable from D
(i.e., {A, B, C, E, F, I, J}
),
while passing as well --ancestry-path=F
, filters-out commit E
from that set,
because E
cannot be reached from F
and F
cannot be reached from E
.
A diff
particularity¶
It is worth pointing out that in the context of the git diff
command,
<rev1>..<rev2>
and <rev1>...<rev2>
do not represent ranges:
However, diff is about comparing two endpoints, not ranges, and the range notations … do not mean a range
A nice summary of using the range notation with git log
and git diff
can be
found here.