34

I have seen git commands use a syntax such as HEAD~, but I haven't been able to find this syntax in the Git Reference Manual.

Here is what I have understood: <commit>~<n> refers to the commit <n> steps earlier than <commit> (where <n> is an integer number), and commit~ simply means the same and that <n> implicitly is one.

Now, is this correct? In that case, does this always work? What if <commit> is the result of a merge between two branches, which commit will then <commit>~ refer to? Is there some corresponding syntax for referring to the next commit or the commit <n> steps later?

HelloGoodbye
  • 3,624
  • 8
  • 42
  • 57

5 Answers5

30

You have a very clear explanation of how this works in the chapter on Acenstry References in Pro Git:

  • ~ is used to get the first parent.
  • ^ can be used to get the other parents (^2, for example, for a merge).

But you don't have a simple way to reference the next commit, even if there are more convoluted ways to get it.

cexbrayat
  • 17,772
  • 4
  • 27
  • 22
  • 1
    Thanks. The reference manual was apparently not the right place to look — I thought it would cover Git's syntax as well. – HelloGoodbye Apr 17 '13 at 15:46
19

To simply answer the question from title (since that's what got me here from Google):

To checkout the previous commit:

git checkout HEAD^

To checkout the next commit (assuming there's no branching):

git checkout `git log --reverse --ancestry-path HEAD..master | head -n 1 | cut -d \  -f 2`
Hubert OG
  • 19,314
  • 7
  • 45
  • 73
13

Inspired by @cexbrayat's answer, I find it useful to think of it this way:

How to refer to something in a commit's ancestry, where a commit can have multiple parents:

  • ^n specifies which parent

  • ~n specifies which generation

Both default to one.

Jon Carter
  • 2,836
  • 1
  • 20
  • 26
  • 1
    That's a quite good rule :) Although it breaks down when neither `^n` nor `~n` is specified. – HelloGoodbye Oct 30 '15 at 19:16
  • That just leaves the commit hash itself, which refers to.. itself. I suppose I should have specified that a commit hash should be included as well. Is that what you mean? – Jon Carter Oct 30 '15 at 19:20
  • 1
    I guess you mean that they default to one, like arguments to a function in programming can have default values if you don't specify them? I'm thinking that if you have a function that takes both which generation and which parent and returns a commit reference, and if you don't specify any of them, you will just have the commit you start out with. So in this case the generation would be 0 even though you don't specify which generation. Although I realize that which parent is really only relevant when the generation in 1, so the two having such a function doesn't make so much sense. – HelloGoodbye Oct 31 '15 at 11:57
  • 1
    In other words, the default value of the generation would be 0 if you don't specify which parent. – HelloGoodbye Oct 31 '15 at 11:59
  • 1
    Well, what I mean by 'default to one': Consider the expression '^'. There is no specific value given for which parent you mean, so the first parent is returned. Same with '~'. No number is specified, so the first generation back is what it acts upon. – Jon Carter Nov 02 '15 at 01:40
4

To refer to most recent commit on the branch you can also use @~1

git checkout @~1
Jon Portella
  • 1,068
  • 9
  • 8
0

Like the OP, I was looking for the official documentation on this subject and found this SO question instead. See Git - Revision Selection.

davidvandebunte
  • 1,286
  • 18
  • 25