The difference is a bit of a vertical vs horizontal matter.
In Git, commits are a type of linked list, each commit has a reference to a parent commit, or to multiple parent commits.
Accessing a parent, or a grand-parent, is done with ~
:
~
is the direct parent of a commit,
~2
(or ~~
) is the grand-parent
- and so on
This is the vertical side, if you look at a log, using ~
will make you go down through the commits.
Now, when you merge two branches, it makes a merge commit. A merge commit, by definition, is merging two, or more, branches together. So the merge commit will have two or more parents.
From the merge commit, if you want to access different parents, you use ^
(it actually looks like a merge of two branches).
So consider this part of log:
* 39a2f899 (HEAD)
|\
| * e2e7d241 (BRANCH)
| * caf13dc1
| * 609a9715
|/
* 663e09ff
If you want to access the parent commit of BRANCH
, you would do BRANCH~
, or e2e7d241~
, which would give caf13dc1
. Now if you want to access the parent of HEAD
, and do HEAD~
, it will give you 663e09ff
(the commit before the branch started).
But if you want to access the chain of commits of the merged branch, that's where ^
comes in the game, you would do HEAD^2
, to say the "second parent of HEAD" (not the parent's parent).
You can of course combine them, in the same graph, HEAD^2~
is the parent (~
) of the second parent (^2
) of HEAD, which is caf13dc1
Incidentally, every commit has at least 1 parent, so commit^
is always the same as commit~
. On the other hand, if a commit has a single parent (it is not a merge commit), commit^2
will return an error.
To sum up, you access different parents of a merge with ^
and you access generations of commits with ~
.
It can be illustrated as follow with a more complex merge (of 4 branches merged at once):
----------> use ^ to go through the parents of the merge
|
| *-----. 6af2936d
| |\ \ \ \
| | | | | * 20d6fb23 BRANCH1
| | | | * | e589d446 BRANCH2
| | | | * | ec6088bd
| | | | |/
| | | * | 38dcecfa BRANCH3
| | | |/
| | * | 698c3daa BRANCH4
| | |/
| |/
| * 2d97958e
| |\
| | * 8989f1d3
| | * d907cb7a
| |/
| * af368002
V
use ~ to go this way (through the ancestors)