Reputation: 6687
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
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
~
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
~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
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 existbb
is a merge commit, with 2 parents: bb^
is gg
(same as bb~
), bb^2
is cc
, bb^3
does not exist^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
...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
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