269

What are the differences 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>
  1. Changes between the tips of the topic and the master branches.
  2. Same as above.
  3. Changes that occurred on the master branch since when the topic branch was started off it.

but isn't totally clear to me.

chrisjlee
  • 21,691
  • 27
  • 82
  • 112

5 Answers5

433

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

An illustration of the different ways of specifying commits for git diff

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:

An illustration of the different ways of specifying ranges of commits for git log

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.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
  • 1
    I like your diagrams. [I came up with my own a while ago too](http://stackoverflow.com/a/24186641/456814). I have some ideas for my own `git diff` diagrams that I'll make later. –  Jul 31 '14 at 23:53
  • 52
    Did someone notice? The effects of `..` and `...` feel _reversed_ in `git diff` (compared to `git rev-list`)! – Robert Siemer Feb 19 '15 at 11:47
  • 3
    You had me at "That's all you need to know [...]. However...". :-) Git is full of things like this where similar notation and terminology means different things in different contexts; thanks for clarifying this so well. – ShreevatsaR Jul 09 '15 at 08:53
  • Thanks for mentioning rev-list. I came across this question while looking for a way of doing what rev-list does via rev-parse. – Mad Physicist Jul 13 '16 at 16:11
  • "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." What exactly do you mean by the "difference between the tips of the two branches"? – Asad Moosvi Jul 30 '17 at 12:09
  • What about when you do git rev-list sha1..sha2 on the same branch? What would be the difference then between that and sha1...sha2? – Almenon Aug 02 '19 at 04:15
  • What is `^` in the `git rev-list bar ^foor`? – foxiris Jul 06 '21 at 06:42
  • 1
    @foxiris When `^` comes just before something that refers to a commit, it means "not". So `git rev-list bar ^foo` means "everything that is in bar, except for anything in `foo`" – Mark Longair Jul 07 '21 at 08:25
101

My consolidated version of the .. vs ... with diff vs log

Diff vs Log & .. vs ..

icc97
  • 11,395
  • 8
  • 76
  • 90
DolphinDream
  • 1,235
  • 1
  • 9
  • 5
  • 4
    this would be very good, if only it didn't have so many different colors and set operations mixed up together with `..`/`...` stuff. For example in `log A...B` it is not clear whether the command returns the intersection (white part of the diagram) or the rest of the A-B union (green). It would be more to the point without any set operands and with only 1 color. – xealits Jan 30 '18 at 11:41
  • 2
    Should this really be `diff A..B` <—> `log A...B`, that is, does really *diff* with 2 dots, correspond to *log* with 3 (!) dots? Or is there a typo in the image. Looking at how the dots are color coded, seems to me there's a typo in the image. The lower left corner: `log A...B` should be `log A..B`, right (?). And *log* just to the right should be `...` not `..`. – KajMagnus Jan 09 '19 at 13:28
  • 1
    Hi DolphinDream, thanks for your figure. I use it as reference here: https://gitlab.com/tortoisegit/tortoisegit/issues/3427#note_227200695 – Yue Lin Ho Oct 14 '19 at 06:55
  • 3
    @KajMagnus actually the red/blue colors are just used to distinguish between 2-dots and 3-dots (regardless of being used with diff or log). The diagram is correct. In the first column, the result of diff with 2-dots is similar to the log with 3-dots (hence the whole purpose diagram to begin with). The diff with 2-dots gives the code changes in both revs down to the divergence point (illustrated by the green bubbles around the commits and the green parts of the van diagrams) while log with 3-dots gives the change logs (commit messages) in both revs down to the divergence point. – DolphinDream Nov 07 '19 at 14:54
  • Is there a mnemonic for this difference between `A B`, `A..B` and `A...B` for `diff` and `log`? How does it make sense, or how is it logically explainable? For `log` I think it's a bit easier than for `diff`, but it's just hard to come up with it naturally for all six cases. – Erik Oct 23 '20 at 08:57
  • 3
    @KajMagnus It seems confusing and contradictory because `git log` and `git diff` both treat `...` differently. _log_ uses gitrevisions (see `man 7 gitrevisions`) to parse the `...`, but _diff_ doesn't. _diff_ uses its own definition of `...` that is different from the one used by gitrevisions. – snath03 Jul 31 '22 at 16:37
  • 1
    unrelated: Hey @DolphinDream how did you make this diagram? I'd like to learn how to make such diagrams. Any tips? – snath03 Jul 31 '22 at 16:42
  • 2
    @snath03 It’s been awhile, but I think I used LibreOffice Draw to make it. – DolphinDream Aug 01 '22 at 18:25
  • @xealits, the coloring makes sense to me: the `git log` "operator" is green, hence its operation result set is colored green (in the Venn diagrams, as well as in the graph diagrams). – Abdull Dec 14 '22 at 12:12
  • @xealits personally I love the colours, the diagram is gorgeous and makes very good use of specific colours to link the venn diagrams and the parts of the tree. – icc97 Jan 30 '23 at 17:21
37

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
icc97
  • 11,395
  • 8
  • 76
  • 90
manojlds
  • 290,304
  • 63
  • 469
  • 417
  • 2
    git diff foo...master changes that master branch has introduced since it's common ancestor with foo – 0fnt Jan 29 '14 at 15:51
  • @manojlds ok, so different question, if you're at dev branch and commit your changes (the function) and push the changes into a remote dev branch does this mean the visible change is only the function or the function and the readme? – David Jan 23 '17 at 13:40
  • 1
    If I am not mistaken, GitHub's pull request diff uses the triple dot. Is that right? – Shaun Luttin Mar 21 '17 at 19:08
  • 1
    Broken link to GitHub example page. – K.-Michael Aye May 13 '19 at 22:59
  • 1
    I never knew the 3 dot (`...`) version existed. I've always used `git diff $(git merge-base master dev) dev` instead of `git diff master...dev`, but they appear to be equivalent. So, for anyone wondering, apparently `git diff master...dev` is the same thing as `git diff $(git merge-base master dev) dev`. – Gabriel Staples Sep 09 '20 at 19:38
6
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.

icc97
  • 11,395
  • 8
  • 76
  • 90
italiano40
  • 496
  • 9
  • 18
2

git log tree

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
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
yanhaijing
  • 21
  • 5