What's the difference between HEAD^ and HEAD~ in Git?
Asked Answered
M

17

1230

When I specify an ancestor commit object in Git, I'm confused between HEAD^ and HEAD~.

Both have a "numbered" version like HEAD^3 and HEAD~2.

They seem very similar or the same to me, but are there any differences between the tilde and the caret?

Mage answered 8/2, 2010 at 12:56 Comment(0)
I
1355

Rules of thumb

  • Use ~ most of the time — to go back a number of generations, usually what you want
  • Use ^ on merge commits — because they have two or more (immediate) parents

Mnemonics:

  • Tilde ~ is almost linear in appearance and wants to go backward in a straight line
  • Caret ^ suggests an interesting segment of a tree or a fork in the road

Tilde

The “Specifying Revisions” section of the git rev-parse documentation defines ~ as

<rev>~<n>, e.g. master~3
A suffix ~<n> to a revision parameter means the commit object that is the nth generation ancestor of the named commit object, following only the first parents. For example, <rev>~3 is equivalent to <rev>^^^ which is equivalent to <rev>^1^1^1

You can get to parents of any commit, not just HEAD. You can also move back through generations: for example, master~2 means the grandparent of the tip of the master branch, favoring the first parent on merge commits.

Caret

Git history is nonlinear: a directed acyclic graph (DAG) or tree. For a commit with only one parent, rev~ and rev^ mean the same thing. The caret selector becomes useful with merge commits because each one is the child of two or more parents — and strains language borrowed from biology.

HEAD^ means the first immediate parent of the tip of the current branch. HEAD^ is short for HEAD^1, and you can also address HEAD^2 and so on as appropriate. The same section of the git rev-parse documentation defines it as

<rev>^, e.g. HEAD^, v1.5.1^0
A suffix ^ to a revision parameter means the first parent of that commit object. ^<n> means the nth parent ([e.g.] <rev>^ is equivalent to <rev>^1). As a special rule, <rev>^0 means the commit itself and is used when <rev> is the object name of a tag object that refers to a commit object.

Examples

These specifiers or selectors can be chained arbitrarily, e.g., topic~3^2 in English is the second parent of the merge commit that is the great-grandparent (three generations back) of the current tip of the branch topic.

The aforementioned section of the git rev-parse documentation traces many paths through a notional git history. Time flows generally downward. Commits D, F, B, and A are merge commits.

Here is an illustration, by Jon Loeliger. Both commit nodes B and C are parents of commit node A. Parent commits are ordered left-to-right. (N.B. The git log --graph command displays history in the opposite order.)

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A

A =      = A^0
B = A^   = A^1     = A~1
C = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2

Run the code below to create a git repository whose history matches the quoted illustration.

#! /usr/bin/env perl

use strict;
use warnings;
use subs qw/ postorder /;
use File::Temp qw/ mkdtemp /;

my %sha1;
my %parents = (
  A => [ qw/ B C /               ],
  B => [ qw/     D E F /         ],
  C => [ qw/         F /         ],
  D => [ qw/           G H /     ],
  F => [ qw/               I J / ],
);

sub postorder {
  my($root,$hash) = @_;
  my @parents = @{ $parents{$root} || [] };
  postorder($_, $hash) for @parents;
  return if $sha1{$root};
  @parents = map "-p $sha1{$_}", @parents;
  chomp($sha1{$root} = `git commit-tree @parents -m "$root" $hash`);
  die "$0: git commit-tree failed" if $?;
  system("git tag -a -m '$sha1{$root}' '$root' '$sha1{$root}'") == 0 or die "$0: git tag failed";
}

$0 =~ s!^.*/!!;  # / fix Stack Overflow highlighting
my $repo = mkdtemp "repoXXXXXXXX";
chdir $repo or die "$0: chdir: $!";
system("git init") == 0               or die "$0: git init failed";
chomp(my $tree = `git write-tree`);      die "$0: git write-tree failed" if $?;

postorder 'A', $tree;
system "git update-ref HEAD   $sha1{A}"; die "$0: git update-ref failed" if $?;
system "git update-ref master $sha1{A}"; die "$0: git update-ref failed" if $?;

# for browsing history - http://blog.kfish.org/2010/04/git-lola.html
system "git config alias.lol  'log --graph --decorate --pretty=oneline --abbrev-commit'";
system "git config alias.lola 'log --graph --decorate --pretty=oneline --abbrev-commit --all'";

It adds aliases in the new throwaway repo only for git lol and git lola so you can view history as in

$ git lol
*   29392c8 (HEAD -> master, tag: A) A
|\
| * a1ef6fd (tag: C) C
| |
|  \
*-. \   8ae20e9 (tag: B) B
|\ \ \
| | |/
| | *   03160db (tag: F) F
| | |\
| | | * 9df28cb (tag: J) J
| | * 2afd329 (tag: I) I
| * a77cb1f (tag: E) E
*   cd75703 (tag: D) D
|\
| * 3043d25 (tag: H) H
* 4ab0473 (tag: G) G

Note that on your machine the SHA-1 object names will differ from those above, but the tags allow you to address commits by name and check your understanding.

$ git log -1 --format=%f $(git rev-parse A^)
B
$ git log -1 --format=%f $(git rev-parse A~^3~)
I
$ git log -1 --format=%f $(git rev-parse A^2~)
F

The “Specifying Revisions” in the git rev-parse documentation is full of great information and is worth an in-depth read. See also Git Tools - Revision Selection from the book Pro Git.

Order of Parent Commits

The commit 89e4fcb0dd from git’s own history is a merge commit, as git show 89e4fcb0dd indicates with the Merge header line that displays the immediate ancestors’ object names.

commit 89e4fcb0dd01b42e82b8f27f9a575111a26844df
Merge: c670b1f876 649bf3a42f b67d40adbb
Author: Junio C Hamano <[email protected]>
Date:   Mon Oct 29 10:15:31 2018 +0900

    Merge branches 'bp/reset-quiet' and 'js/mingw-http-ssl' into nd/config-split […]

We can confirm the ordering by asking git rev-parse to show 89e4fcb0dd’s immediate parents in sequence.

$ git rev-parse 89e4fcb0dd^1 89e4fcb0dd^2 89e4fcb0dd^3
c670b1f876521c9f7cd40184bf7ed05aad843433
649bf3a42f344e71b1b5a7f562576f911a1f7423
b67d40adbbaf4f5c4898001bf062a9fd67e43368

Querying the non-existent fourth parent results in an error.

$ git rev-parse 89e4fcb0dd^4
89e4fcb0dd^4
fatal: ambiguous argument '89e4fcb0dd^4': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

If you want to extract the parents only, use pretty format %P for the full hashes

$ git log -1 --pretty=%P 89e4fcb0dd
c670b1f876521c9f7cd40184bf7ed05aad843433 649bf3a42f344e71b1b5a7f562576f911a1f7423 b67d40adbbaf4f5c4898001bf062a9fd67e43368

or %p for abbreviated parents.

$ git log -1 --pretty=%p 89e4fcb0dd
c670b1f876 649bf3a42f b67d40adbb
Incivility answered 8/2, 2010 at 16:6 Comment(16)
it seems ^ can handle all the cases and one can wonder why ~ appeared in the first place. Why not remember only how ^ works ?Towards
this is super confusing still... assuming G is HEAD, so if I do a HEAD^ that would be D... right?Cannice
@duckx the graph is actually going top-to-bottom, so A is the most recent commit, and G is one of the oldest. The path from G to D is forward, not backward, from what I can tell.Adaptable
@SimonBudin I guess, it's not very convenient to use ^^^^^^^ instead of ~7, is it? That's why ~ is usefulApatetic
what is a use case for ~? how could you use this without knowing which commit you'll land on?Samul
@Samul • It's used relative to HEAD or some specific commit SHA. HEAD~7 is seven generations back following the first-most parent lineage. Same as HEAD^1^1^1^1^1^1^1.Retaretable
TL;DR; <rev>~<n> goes up n parents from rev, selecting the first parent each time. Use <rev>^<n> to select a specific parent. A git commit can have multiple parents (when merging), if you need to select a specific one use ^.Nial
How can git tell which one among B and C is the first parent of A? Based on time of commit?Kristykristyn
I found this davidchudzicki.com/posts/first-parent. Any more tips on how to determine the first parent?Kristykristyn
@GregBacon here's the question https://mcmap.net/q/22428/-how-to-determine-which-parent-is-the-first-one-for-a-merge-commit-in-git/2498327Kristykristyn
@Sbu, good question. As far as I can see one could select any commit just by using "^". Now, it would make it more difficult to express than by also having "~"Putput
If above was a little hard to understand (it was for me), then this article is a little more easy to understand: salferrarello.com/git-head-tilde-vs-head-caretRemittance
Extra thought view for ~ (squiggle/tilde) is a line of waves (of commits) lapping at the shore, while ^ (caret) is multiple surf breaks along the same wave crest (forking and merging..). Whatever works for you - the one you think up will be most memorable to you ;-)Sommelier
The graph was super helpful, but I found it very confusing that it goes from top to bottom. I wrote a similar explanation here where the the graph goes from bottom to top, as is usually the case when viewing commit graphs.Cloudscape
I could not understand, why C = A^2 instead C=A^1, is it not same level with B? @MarkLakataBarbarian
@IchigoKurosaki Yes, B and C are at the same level, but B = A^1 (the first immediate parent) and C = A^2 (the second immediate parent).Incivility
T
394

The difference between HEAD^ and HEAD~ is well described by the illustration (by Jon Loeliger) found on http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html.

This documentation can be a bit obscure to beginners so I've reproduced that illustration below:

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A
A =      = A^0
B = A^   = A^1     = A~1
C = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2
Truncate answered 21/9, 2012 at 9:11 Comment(10)
Just one question. How is it possible for a commit to have more than two parents? (See B - it's parents are D, E and F) I imagine that the only way a commit can have two parents is when it is a merge commit... but how can you merge 3 commits at the same time?Goldberg
If I'm not mistaken, this may be obvious, but I think it should be specified that HEAD~ follows the current branch (like Diego Dias mentioned below).Antiphon
Additionally, F = A^2^.Lunate
So, ^ == ^1 == LEFTMOST PARENT, ^2 == SECOND LEFTMOST PARENT and so forth. And ~ == ~1 == LEFTMOST PARENT, ~2 == LEFTMOST PARENTS LEFTMOST PARENT == LEFTMOST GRANDPARENT. By extension, ~2^2 == LEFTMOST GRANDPARENTS SECOND LEFTMOST PARENTDrumfire
@AlexanderTorstling this was very helpful for me. However, what does left and right mean here?Ancient
@tsikov If you're on branch A, you can do git merge B C. That's a 3-way merge.Cutpurse
@tsikov @Julian A. Or in the case of this illustration, someone was on branch D, and ran git merge E F. The resulting commit was B.Darkness
How does Git know that B = A^1 and C = A^2, and not vice-versa. To me, B and C look indistinguishable, in that all we know about them is that they were merged to create A. That is, why shouldn't we assume B = A^2 and C = A^1 ? The diagram alone doesn't give any real reason to assume one way or another, as far as I can tell.Bolten
I see why now. There is a critical fact in the original source: Parent commits are ordered left-to-right.. This should probably be included as part of the answer.Bolten
Is A = A^0 = A~ missing? I arrived here to check if HEAD and HEAD~ are equivalent, it might be useful to add it.Reiter
B
352

Both ~ and ^ on their own refer to the parent of the commit (~~ and ^^ both refer to the grandparent commit, etc.) But they differ in meaning when they are used with numbers:

  • ~2 means up two levels in the hierarchy, via the first parent if a commit has more than one parent

  • ^2 means the second parent where a commit has more than one parent (i.e. because it's a merge)

These can be combined, so HEAD~2^3 means HEAD's grandparent commit's third parent commit.

Benzofuran answered 17/5, 2014 at 18:55 Comment(4)
Reading this followed by the picture from stackoverflow.com/questions/2221658/… made perfect sense.Patrilineal
This answer made me distinguish between caret/tilde without number and with number! I thought ^^ was the same as ^2 but it's not .Clotheshorse
branch^ and branch~ are the same thing. Well done for leading with that point - I came here wondering whether to type git reset HEAD^ or git reset HEAD~. If I'd read this answer first, I could have left a lot sooner.Darkness
This should be the answer because this answer zeros in on the only meaningful difference between ~ and ^ while cutting out all the fluff (though the other answers have useful graphs where you can mentally practice understanding and so also provide value).Avaria
L
319

My two cents...

enter image description here

Lantana answered 18/3, 2015 at 11:30 Comment(5)
And how H=A~2^2 not H=A~2^1?Waterside
If I had figured it out correctly, the commits A, B, D, G are on the same branch and the commit D is a merge of G and H, therefore having two parents. So the commit (H) from other branch is reference by ^2.Waterside
Thank you. How do I know whether G or H is the first or second immediate ancestor of D if I don't have a pretty graph? git cat-file -p D and look at the list of parents?Chariot
The arrow ~2 is relative to commit A, not B, so it should start at A, not B.Tarry
Note) Regarding @MohammadFaisal's comment: According to Git glossary, 'branch' and 'branch head' have different meanings. 'branch head' is a named reference to the commit of a branch (like a pointer to a commit). However, many people use the term 'branch' to mean 'branch head'. Note that HEAD is a reference to one of the 'branch head's, except when it's a detached HEAD.Demibastion
S
101

Here's a very good explanation taken verbatim from http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde :

ref~ is shorthand for ref~1 and means the commit's first parent. ref~2 means the commit's first parent's first parent. ref~3 means the commit's first parent's first parent's first parent. And so on.

ref^ is shorthand for ref^1 and means the commit's first parent. But where the two differ is that ref^2 means the commit's second parent (remember, commits can have two parents when they are a merge).

The ^ and ~ operators can be combined.

enter image description here

Seidule answered 27/3, 2017 at 12:24 Comment(1)
note that in this diagram, time proceeds upwards (unlike the other diagrams on this page).Mudlark
L
46

Simplistically:

  • ~ specifies ancestors
  • ^ specifies parents

You can specify one or more branches when merging. Then a commit has two or more parents and then ^ is useful to indicate parents.

Suppose you are on branch A and you have two more branches: B and C.

On each branch the three last commits are:

  • A: A1, A2, A3
  • B: B1, B2, B3
  • C: C1, C3, C3

If now on branch A you execute the command:

git merge B C

then you are combining three branches together (here your merge commit has three parents)

and

~ indicates the n'th ancestor in the first branch, so

  • HEAD~ indicates A3
  • HEAD~2 indicates A2
  • HEAD~3 indicates A1

^ indicates the n'th parent, so

  • HEAD^ indicates A3
  • HEAD^2 indicates B3
  • HEAD^3 indicates C3

The next use of ~ or ^ next to each other is in the context of the commit designated by previous characters.

Notice 1:

  • HEAD~3 is always equal to: HEAD~~~ and to: HEAD^^^ (every indicates A1),

        and generally:

  • HEAD~n is always equal to: HEAD~...~ (n times ~) and to: HEAD^...^ (n times ^).

Notice 2:

  • HEAD^3 is not the same as HEAD^^^ (the first indicates C3 and the second indicates A1),

        and generally:

  • HEAD^1 is the same as HEAD^,
  • but for n > 1: HEAD^n is always not the same as HEAD^...^ (n times ^).
Lightweight answered 28/8, 2017 at 9:55 Comment(0)
T
37

The ^<n> format allows you to select the nth parent of the commit (relevant in merges). The ~<n> format allows you to select the nth ancestor commit, always following the first parent. See git-rev-parse's documentation for some examples.

Tessellated answered 8/2, 2010 at 13:3 Comment(0)
A
32

It is worth noting that git also has a syntax for tracking "from-where-you-came"/"want-to-go-back-now" - for example, HEAD@{1} will reference the place from where you jumped to new commit location.

Basically HEAD@{} variables capture the history of HEAD movement, and you can decide to use a particular head by looking into reflogs of git using the command git reflog.

Example:

0aee51f HEAD@{0}: reset: moving to HEAD@{5}
290e035 HEAD@{1}: reset: moving to HEAD@{7}
0aee51f HEAD@{2}: reset: moving to HEAD@{3}
290e035 HEAD@{3}: reset: moving to HEAD@{3}
9e77426 HEAD@{4}: reset: moving to HEAD@{3}
290e035 HEAD@{5}: reset: moving to HEAD@{3}
0aee51f HEAD@{6}: reset: moving to HEAD@{3}
290e035 HEAD@{7}: reset: moving to HEAD@{3}
9e77426 HEAD@{8}: reset: moving to HEAD@{3}
290e035 HEAD@{9}: reset: moving to HEAD@{1}
0aee51f HEAD@{10}: reset: moving to HEAD@{4}
290e035 HEAD@{11}: reset: moving to HEAD^
9e77426 HEAD@{12}: reset: moving to HEAD^
eb48179 HEAD@{13}: reset: moving to HEAD~
f916d93 HEAD@{14}: reset: moving to HEAD~
0aee51f HEAD@{15}: reset: moving to HEAD@{5}
f19fd9b HEAD@{16}: reset: moving to HEAD~1
290e035 HEAD@{17}: reset: moving to HEAD~2
eb48179 HEAD@{18}: reset: moving to HEAD~2
0aee51f HEAD@{19}: reset: moving to HEAD@{5}
eb48179 HEAD@{20}: reset: moving to HEAD~2
0aee51f HEAD@{21}: reset: moving to HEAD@{1}
f916d93 HEAD@{22}: reset: moving to HEAD@{1}
0aee51f HEAD@{23}: reset: moving to HEAD@{1}
f916d93 HEAD@{24}: reset: moving to HEAD^
0aee51f HEAD@{25}: commit (amend): 3rd commmit
35a7332 HEAD@{26}: checkout: moving from temp2_new_br to temp2_new_br
35a7332 HEAD@{27}: commit (amend): 3rd commmit
72c0be8 HEAD@{28}: commit (amend): 3rd commmit

An example could be that I did local-commits a->b->c->d and then I went back discarding 2 commits to check my code - git reset HEAD~2 - and then after that I want to move my HEAD back to d - git reset HEAD@{1}.

Antirachitic answered 20/2, 2014 at 14:49 Comment(4)
Thanks for this. Its basically a "goto" to the commit I was {N} times before. Very useful!Putput
The HEAD@{N} notation doesn't seem to work on git 2.26, and I fail to find information as to whyPutput
Dont know why can't update previous comment,sorry for that. But above comment is true for tcsh, in case someone runs into same issue! On bash it works fine! On tcsh you need to enclose it in @{} in ""Putput
Thanks this is super useful. There seems to be little resource about HEAD@{n} syntax. Any link to the document?Phase
L
26

An actual example of the difference between HEAD~ and HEAD^:

HEAD^ VS HEAD~

Lipsey answered 4/8, 2018 at 6:36 Comment(0)
O
23

TLDR

~ is what you want most of the time, it references past commits to the current branch

^ references parents (git-merge creates a 2nd parent or more)

A~ is always the same as A^
A~~ is always the same as A^^, and so on
A~2 is not the same as A^2 however,
because ~2 is shorthand for ~~
while ^2 is not shorthand for anything, it means the 2nd parent

Osiris answered 26/1, 2018 at 16:36 Comment(0)
L
17

HEAD^^^ is the same as HEAD~3, selecting the third commit before HEAD

HEAD^2 specifies the second head in a merge commit

Leucocyte answered 8/2, 2010 at 13:1 Comment(0)
M
12

OP: When I specify an ancestor commit object in Git, I'm confused between HEAD^ and HEAD~.

What's the difference between HEAD^ and HEAD~ in Git?

The difference between HEAD^ (Caret) and HEAD~ (Tilde) is how they traverse history backwards from a specified starting point, in this particular case HEAD.

Tilde ~

<rev>~[<n>] = select <n>th generation ancestor, following only first* parents

Caret ^

<rev>^[<n>] = select <n>th parent of first generation ancestors

*First parent is always the left hand side of the merge, e.g. the commit on the branch that got merged into.

Joining ~ and ^ together

As seen in the illustration below the two selectors ~ and ^ can be used in combination. Also note that instead of using HEAD as a starting point, any regular reference can be used such as a branch, tag or even a commit hash.

Further more, depending on what ancestor is intended to be selected ^ and ~ can be used interchangeably as seen below in the table.

Illustration of relative references in Git

Source: A thorough rundown can be found in this blog post on the subject.

Macmacabre answered 26/5, 2022 at 11:3 Comment(0)
E
11
  • HEAD~ specifies the first parent on a "branch"

  • HEAD^ allows you to select a specific parent of the commit

An Example:

If you want to follow a side branch, you have to specify something like

master~209^2~15
Ewaewald answered 8/2, 2010 at 13:5 Comment(0)
S
9

^ BRANCH Selector
git checkout HEAD^2
Selects the 2nd branch of a (merge) commit by moving onto the selected branch (one step backwards on the commit-tree)

~ COMMIT Selector
git checkout HEAD~2
Moves 2 commits backwards on the default/selected branch


Defining both ~ and ^ relative refs as PARENT selectors is far the dominant definition published everywhere on the internet I have come across so far - including the official Git Book. Yes they are PARENT selectors, but the problem with this "explanation" is that it is completely against our goal: which is how to distinguish the two... :)

The other problem is when we are encouraged to use the ^ BRANCH selector for COMMIT selection (aka HEAD^ === HEAD~).
Again, yes, you can use it this way, but this is not its designed purpose. The ^ BRANCH selector's backwards move behaviour is a side effect not its purpose.

At merged commits only, can a number be assigned to the ^ BRANCH selector. Thus its full capacity can only be utilised where there is a need for selecting among branches. And the most straightforward way to express a selection in a fork is by stepping onto the selected path / branch - that's for the one step backwards on the commit-tree. It is a side effect only, not its main purpose.

Stead answered 2/10, 2020 at 14:45 Comment(0)
P
5

~ means parent.

^ if it has two or more parents, like a merge commit. We can select the second of the parent or another.

So if just one thing like (HEAD~ or HEAD^), it has the same results.

Phipps answered 7/8, 2019 at 6:47 Comment(0)
D
1

If you're wondering whether to type HEAD^ or HEAD~ in your command, just use either:

They're both names for the same commit - the first parent of the current commit.

Likewise with master~ and master^ - both names for the first parent of master.

In the same way as 2 + 2 and 2 x 2 are both 4 - they're different ways of getting there, but the answer is the same.

This answers the question: What's the difference between HEAD^ and HEAD~ in Git?

If you just did a merge (so your current commit has more than one parent), or you're still interested in how the caret and tilde work, see the other answers (which I won't duplicate here) for an in-depth explanation, as well as how to use them repeatedly (e.g.HEAD~~~), or with numbers (e.g.HEAD^2). Otherwise, I hope this answer saves you some time.

Darkness answered 13/7, 2020 at 12:23 Comment(0)
S
0

Simply put, for the first level of parentage (ancestry, inheritance, lineage, etc.) HEAD^ and HEAD~ both point to the same commit, which is (located) one parent above the HEAD (commit).

Furthermore, HEAD^ = HEAD^1 = HEAD~ = HEAD~1. But HEAD^^ != HEAD^2 != HEAD~2. Yet HEAD^^ = HEAD~2. Read on.

Beyond the first level of parentage, things get trickier, especially if the working branch/master branch has had merges (from other branches). There is also the matter of syntax with the caret, HEAD^^ = HEAD~2 (they're equivalent) BUT HEAD^^ != HEAD^2 (they're two different things entirely).

Each/the caret refers to the HEAD's first parent, which is why carets stringed together are equivalent to tilde expressions, because they refer to the first parent's (first parent's) first parents, etc., etc. based strictly on the number on connected carets or on the number following the tilde (either way, they both mean the same thing), i.e. stay with the first parent and go up x generations.

HEAD~2 (or HEAD^^) refers to the commit that is two levels of ancestry up/above the current commit (the HEAD) in the hierarchy, meaning the HEAD's grandparent commit.

HEAD^2, on the other hand, refers NOT to the first parent's second parent's commit, but simply to the second parent's commit. That is because the caret means the parent of the commit, and the number following signifies which/what parent commit is referred to (the first parent, in the case when the caret is not followed by a number [because it is shorthand for the number being 1, meaning the first parent]). Unlike the caret, the number that follows afterwards does not imply another level of hierarchy upwards, but rather it implies how many levels sideways, into the hierarchy, one needs to go find the correct parent (commit). Unlike the number in a tilde expression, it is only one parent up in the hierarchy, regardless of the number (immediately) proceeding the caret. Instead of upward, the caret's trailing number counts sideways for parents across the hierarchy [at a level of parents upwards that is equivalent to the number of consecutive carets].

So HEAD^3 is equal to the third parent of the HEAD commit (NOT the great-grandparent, which is what HEAD^^^ AND HEAD~3 would be...).

Stephaniastephanie answered 28/8, 2017 at 17:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.