# Two and three dots with log¶

Note

Remember it’s different for `git diff`

- see Two and three dots with diff and
Pain in the dots

## Logging without dots¶

Two dots is the default in `git log`

. That is, if you do:

```
git log master topic
```

what you’ll get is the same as if you asked for:

```
git log master..topic
```

So logging without dots is the same as Logging with two dots.

## Logging with two dots¶

Let’s say you asked for this:

```
git log start-branch..end-branch
```

You will see a log of a series of commits. The commits will be all the commits
reachable from `end-branch`

that are not reachable from `start-branch`

.

In fact, the two dot form of log is shorthand. The `git log`

line above is
shorthand for:

```
git log ^start-branch end-branch
```

`end-branch`

above means — “show me all commits that can be
reached from `end-branch`

”. `^start-branch`

means — “excluding any
commits that can be reached from `start-branch`

”.

Note

What does “reachable” mean?

A commit, \(s\), can be **reached** from some commit, \(t\), if
and only if there is a path from \(s\) to \(t\) along the ancestry
graph of the commits.

The ancestry graph is the directed acyclic graph of the history, where the nodes are the commits and the edges are directed backwards from nodes to their parents.

Put more formally, a sequence of commits, \(v_0, v_1, ..., v_n\),
forms a **path** between \(v_0\) and \(v_n\) if and only if
\(v_{i-1}\) is the parent of \(v_i\) for \(i=1\) to
\(i=n\). A commit is also reachable from itself, so a commit sequence
of length 1 is defined as forming a path.

Obviously `git log start-branch..end-branch`

cannot include the commit
pointed to by `start-branch`

because you can always reach `start-branch`

from itself.

Let’s say we have this history:

```
H--I--J topicB
/
| E---F---G topicA
|/
A---B---C---D master
```

What would `git log topicB..topicA`

show? From `topicA`

we can
reach `G, F, E, D, C, B, A`

. From `topicB`

we can reach ```
J, I, H, D, C, B,
A
```

. So, the commits reachable from `topicA`

but not reachable from
`topicB`

are `G, F, E`

.

## Logging with three dots¶

Now you ask for this:

```
git log start-branch...end-branch
```

There are three dots between `start-branch`

and `end-branch`

. This three
dot version of the command finds all commits that are reachable from
`start-branch`

, OR that are reachable from `end-branch`

BUT that are NOT
reachable from both `start-branch`

AND `end-branch`

.

Put another way, you will see all commits reachable from `start-branch`

AND
all commits reachable from `end-branch`

BUT excluding any commits reachable
from any common ancestor. As the `gitrevisions`

man page puts it, the three
dots command above is equivalent to:

```
git log start-branch end-branch --not $(git merge-base --all start-branch end-branch)
```

Put another way, if \(S\) is the set of all commits that can be reached from
`start-branch`

and \(E\) is the set of all commits that can be reached
from `end-branch`

then the commits returned from the three dot version of log
are:

(\(X \setminus Y\) denotes the set of members of \(X\) that are not in set \(Y\)).

By example, from the history above, let’s think about what would we get from:

```
git log topicB...topicA
```

From `topicA`

we can reach this set of commits — ```
G, F, E, D, C, B,
A
```

. From `topicB`

we can reach `J, I, H, D, C, B, A`

. That means that we
can reach `D, C, B, A`

from both of `topicA`

AND `topicB`

. So the
returned commits would be `G, F, E, J, I, H`

.