Miguel Trejo
Miguel Trejo

Reputation: 6687

What does HEAD~n^k does on git?

I notice that one can specify ancestors of actual commit by using the ^ or the ~ character. For example, if I have the following log of commits

* 1990f31 Somme third commit message 
* k135145 Somme second commit message 
* 2c13521 Somme first commit message 

then I can know which is the parent commit of 1990f31 with HEAD^1 (or equivalently with HEAD~1), which is k135145.

Now, I also read that one can combine ^ or ~ when it is a merge commit. Therefore, could someone provide an example to illustrate commit references when typing git show HEAD~n^k or alternatively by commuting this operators like git show HEAD^k~n?, where I'm considering n and k as abstractions to represent a positive integer.

Upvotes: 0

Views: 116

Answers (2)

LeGEC
LeGEC

Reputation: 52101

~ and ^ are operators which you can use to designate any ancestor within a commit's history.

Let us start with a diagram :

* aa (HEAD, master) commit
* bb merged branch `some/feature` into master
|\
| * cc (some/feature) feature: completed
| * dd feature: wip
| * ff feature: start
* | gg some fix on master
|/
* hh some commit on master
  • ~ will go up the chain of first parents :

    • aa~ is bb, aa~2 is gg, aa~3 is hh
    • cc~ is dd, cc~2 is ff, cc~3 is also hh
    • but using ~ alone, and starting from aa, you will not be able to explore the some/feature branch : at the merge point (bb), cc is the second parent of bb
    • note that ~n is a shortcut to ~~...~ repeated n times, eg : aa~3 is the same as aa~~~
  • ^ will only go up one level, but allows you to inspect the n-th parent for commits that have several parents

    • calling xx^ is the same as xx~ : in both case, it is the first parent of xx
    • aa is a regular commit, with one single parent: so aa^ is bb (same as aa~), aa^2 does not exist
    • bb is a merge commit, with 2 parents: bb^ is gg (same as bb~), bb^2 is cc, bb^3 does not exist
    • note that ^n is not a shortcut to ^^...^, e.g :
      bb^2 is the second parent of bb (it is cc)
      bb^^ is the first parent of the first parent of bb (it is hh)

In some cases, you can have octopus merge commits, which may have xx^3, xx^4 ... parents.


By combining the operators, you can "navigate" to any ancestor commit.

For example, starting from aa, one way to reach ff is :

aa~^2~2

# some other ways to describe a path to reach `ff` :
aa^^2~2   # to reach the first parent, ~ or ^ are equivalent
aa~^2~~   # ~2 is the same as ~~
aa^^2^^
...

In general, you can't switch ~ and ^ sequences, because they would not point at the same commit.
For example :

aa~^2   # points at cc
aa^2~   # does not exist

Anything that point to a commit can take the palce of aa, bb or cc above :

  • HEAD, a sha1, some/branch, some/tag ...
  • some other refs known to git : stash@{0} (items in the stash), HEAD@{3} (elements in the reflog of HEAD), master@{2} (elements in the reflog of the master branch)
  • ...

Upvotes: 3

eftshift0
eftshift0

Reputation: 30297

HEAD is always where you are. HEAD~n means the nth revision going back (always taking first parent). HEAD~n^k means, from that nth revision back from HEAD, take the kth parent (HEAD~n being a merge revision with at least k parents).

Upvotes: 4

Related Questions