What are the differences between double-dot ".." and triple-dot "..." in Git diff commit ranges?
What are the diff开发者_如何学运维erences between the following commands?:
git diff foo master # a
git diff foo..master # b
git diff foo...master # c
The diff manual talks about it:
Comparing branches
$ git diff topic master <1> $ git diff topic..master <2> $ git diff topic...master <3>
- Changes between the tips of the topic and the master branches.
- Same as above.
- Changes that occurred on the master branch since when the topic branch was started off it.
but isn't totally clear to me.
Since I'd already created these images, I thought it might be worth using them in another answer, although the description of the difference between ..
(dot-dot) and ...
(dot-dot-dot) is essentially the same as in manojlds's answer.
The command git diff
typically¹ only shows you the difference between the states of the tree between exactly two points in the commit graph. The ..
and ...
notations in git diff
have the following meanings:
# Left side in the illustration below:
git diff foo..bar
git diff foo bar # same thing as above
# Right side in the illustration below:
git diff foo...bar
git diff $(git merge-base foo bar) bar # same thing as above
In other words, git diff foo..bar
is exactly the same as git diff foo bar
; both will show you the difference between the tips of the two branches foo
and bar
. On the other hand, git diff foo...bar
will show you the difference between the "merge base" of the two branches and the tip of bar
. The "merge base" is usually the last commit in common between those two branches, so this command will show you the changes that your work on bar
has introduced, while ignoring everything that has been done on foo
in the mean time.
That's all you need to know about the ..
and ...
notations in git diff
. However...
... a common source of confusion here is that ..
and ...
mean subtly different things when used in a command such as git log
that expects a set of commits as one or more arguments. (These commands all end up using git rev-list
to parse a list of commits from their arguments.)
The meaning of ..
and ...
for git log
can be shown graphically as below:
So, git rev-list foo..bar
shows you everything on branch bar
that isn't also on branch foo
. On the other hand, git rev-list foo...bar
shows you all the commits that are in either foo
or bar
, but not both. The third diagram just shows that if you list the two branches, you get the commits that are in either one or both of them.
Well, I find that all a bit confusing, anyway, and I think the commit graph diagrams help :)
¹ I only say "typically" since when resolving merge conflicts, for example, git diff
will show you a three-way merge.
My consolidated version of the ..
vs ...
with diff vs log
git diff foo master
Diff between the tip (head) commits of foo
and master
.
git diff foo..master
Another way of doing the same thing.
git diff foo...master
Diff from the common ancestor (git merge-base foo master
) of foo
and master
to the tip of master
. In other words, it shows only the changes that master
branch has introduced since its common ancestor with foo
.
This Learn.GitHub "what a merge would introduce" example (archived) explains when to use the two:
For instance, if you create a ‘dev’ branch and add a function to a file, then go back to your ‘master’ branch and remove a line from the README, and then run something like this:
$ git diff master dev
It will tell you that a function was added from the first file and a line was added to the README. Why? Because on the branch, the README still has the original line, but on ‘master’ you’ve removed it - so directly comparing the snapshots looks like ‘dev’ added it.
What you really want to compare is what ‘dev’ has changed since your branches diverged. To do that, Git has a nice little shorthand:
$ git diff master...dev
git diff foo master
will show the differences between the foo
and master
branch at that point in time
git diff foo..master
will also show the differences between the foo
and master
branches at that point in time (equivalent to the above).
git diff foo...master
will show all the differences between when the foo
branch was made from the master
branch and after.
So the first two commands are the same and last one shows a wider view of the diff history.
The top picture is equivalent to the bottom graph tree
A0 <- A1 <- A2 <- A3 (master)
\
C0 <- C1 (test)
A picture is worth a thousand words, the difference between ..
...
^
is shown below.
$ git log master..test
# output C0 C1
$ git log ^master test
# output C0 C1
$ git log master…test
# output A1 A2 A3 C0 C1
精彩评论