указание ревизий и диапазонов для Git (Specifying revisions and ranges for Git)
Указание диапазонов (Specifying ranges)
History traversing commands such as git log
operate on a set of
commits, not just a single commit.
For these commands, specifying a single revision, using the
notation described in the previous section, means the set of
commits reachable
from the given commit.
Specifying several revisions means the set of commits reachable
from any of the given commits.
A commit's reachable set is the commit itself and the commits in
its ancestry chain.
There are several notations to specify a set of connected commits
(called a "revision range"), illustrated below.
Commit Exclusions
^<rev> (caret) Notation
To exclude commits reachable from a commit, a prefix ^
notation is used. E.g. ^r1 r2 means commits reachable from
r2 but exclude the ones reachable from r1 (i.e. r1 and its
ancestors).
Dotted Range Notations
The .. (two-dot) Range Notation
The ^r1 r2 set operation appears so often that there is a
shorthand for it. When you have two commits r1 and r2 (named
according to the syntax explained in SPECIFYING REVISIONS
above), you can ask for commits that are reachable from r2
excluding those that are reachable from r1 by ^r1 r2 and it
can be written as r1..r2.
The ... (three-dot) Symmetric Difference Notation
A similar notation r1...r2 is called symmetric difference of
r1 and r2 and is defined as r1 r2 --not $(git merge-base
--all r1 r2). It is the set of commits that are reachable
from either one of r1 (left side) or r2 (right side) but not
from both.
In these two shorthand notations, you can omit one end and let it
default to HEAD. For example, origin.. is a shorthand for
origin..HEAD and asks "What did I do since I forked from the
origin branch?" Similarly, ..origin is a shorthand for
HEAD..origin and asks "What did the origin do since I forked from
them?" Note that .. would mean HEAD..HEAD which is an empty range
that is both reachable and unreachable from HEAD.
Commands that are specifically designed to take two distinct
ranges (e.g. "git range-diff R1 R2" to compare two ranges) do
exist, but they are exceptions. Unless otherwise noted, all "git"
commands that operate on a set of commits work on a single
revision range. In other words, writing two "two-dot range
notation" next to each other, e.g.
$ git log A..B C..D
does not
specify two revision ranges for most commands. Instead
it will name a single connected set of commits, i.e. those that
are reachable from either B or D but are reachable from neither A
or C. In a linear history like this:
---A---B---o---o---C---D
because A and B are reachable from C, the revision range
specified by these two dotted ranges is a single commit D.
Other <rev>^ Parent Shorthand Notations
Three other shorthands exist, particularly useful for merge
commits, for naming a set that is formed by a commit and its
parent commits.
The r1^@ notation means all parents of r1.
The r1^! notation includes commit r1 but excludes all of its
parents. By itself, this notation denotes the single commit r1.
The <rev>^-[<n>] notation includes <rev> but excludes the <n>th
parent (i.e. a shorthand for <rev>^<n>..<rev>), with <n> = 1 if
not given. This is typically useful for merge commits where you
can just pass <commit>^- to get all the commits in the branch
that was merged in merge commit <commit> (including <commit>
itself).
While <rev>^<n> was about specifying a single commit parent,
these three notations also consider its parents. For example you
can say HEAD^2^@, however you cannot say HEAD^@^2.