1

I need to see either (1) log messages from HEAD to ec9cb4106 or (2) rollup diff from HEAD to ec9cb4106. The revision selection page does not appear to discuss it, and I can't get git to accept the obvious choices:

$ git log HEAD .. ec9cb4106
fatal: ec9cb4106: no such path in the working tree.
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

$ git diff HEAD .. ec9cb4106
fatal: ec9cb4106: no such path in the working tree.
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

I'm trying the X .. Y because that 's what git displays when it summarizes an update and it can be fed to git diff.

How do I see either (1) the log messages in the range, or (2) the rollup diff of the range?

jww
  • 97,681
  • 90
  • 411
  • 885
  • 3
    Eliminate the spaces, it's `X..Y` with no spaces here. Or, use `^HEAD ec9cb4106`, i.e., "select ec9cb4106 and all ancestors, then remove HEAD and all ancestors", which is what the set difference notation does. (The latter form is not order-dependent: Git does all the selection first, then all the set-subtraction, at least in principle.) – torek Jun 22 '16 at 21:46
  • Oops, yeah, order is important in the `..` notation and I get swapped around sometimes, especially when switching VCSes. – torek Jun 23 '16 at 00:09

2 Answers2

5

Formatted as answer (and with more care about order): you want git log ec9cb4106..HEAD here (as per comments), i.e., include commits reachable from HEAD but exclude items reachable from ec9cb4106 (including ec9cb4106 itself).

Note that there are no spaces before or after the two dots.

The two-dot notation is shorthand for inclusion-and-exclusion.

In general, commands like git log and git rev-list select a commit "with ancestry", as it were: take the given commit and find its parent(s), the parents' parents, and so on, and visit every such commit. This can be a very large set of commits, so we want some way to prune off uninteresting parts of the commit graph.

For this, git log and git rev-list can do set operations. In general, naming multiple commits gets you a union. For instance, consider a graph like this:

     C--D   <-- branch1
    /
A--B
    \
     E--F   <-- branch2

Naming branch1 selects commit D, which—through the back-pointers—reaches commits C, B, and A, and hence shows you those four commits.

Naming branch2 selects commit F, which reaches commits E, B, and A, and hence shows you those four commits.

Naming both branches selects both D and F, so you see all six commits. Note that you do not see B and A twice: the selection is done first, collecting up all the commits to show, and then the commits are sorted and displayed (once each).

To remove some part of the graph you can tell the revision-walker to start at some commit and remove that commit and all its ancestors. The external syntax for this is a prefix hat ^:

git log branch1 ^branch2

This says "select everything reachable from branch1, then discard everything reachable from branch2". In this case, that would select D, C, B, and A; then discard F, E, B, and A. F and E are not in the original set, but this is not a problem: you can subtract away commits that are not there. Hence there's no need for the negated commit(s) to actually be in the set of ancestors of the positively-selected commit(s).

Git offers a rather ridiculously large set of syntaxes for these, so besides ^X Y, you can write --not X --not Y. The reason for two --nots is that --not persists: --not X Y means ^X ^Y. The second --not cancels out the first.

The two-dot syntax, X..Y, is shorthand for ^X Y (or equivalently (Y ^X). Except for --not persisting, order is irrelevant when using the longer syntax, but important with the two-dot syntax.

Note that git diff treats the two-dot syntax specially. It does not select a range of commits there. (The C source for git diff checks for the literal string .. relatively early, and removes it if it's present, before passing the arguments on to the revision parsing code.)

torek
  • 448,244
  • 59
  • 642
  • 775
1

git lo HEAD..ec9cb4106 or git log ^HEAD ec9cb4106 list all the commits that are reachable from ec9cb4106 excluding those that are reachable from HEAD. If HEAD is ahead of ec9cb4106 or just points to ex9cb4106, the output is nothing. You may need git log ec9cb4106..HEAD or git log ^ec9cb4106 HEAD.git diff HEAD ec9cb4106 or git diff HEAD..ec9cb4106 or git diff ec9cb4106 HEAD or git diff ec9cb4106..HEAD or git diff ec9cb4106(HEAD can be omitted in this case) are all the same.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53