Melad Basilius
Melad Basilius

Reputation: 4306

Git what is the logical difference between parent and ancestor

I know I can find dozens of questions about the difference between HEAD^ and HEAD~

My question is about the difference of meaning of parents and ancestors. for me parent is the same as ancestor.

What is the logical difference between parent and ancestor?

What's the difference between HEAD^ and HEAD~ in Git? doesn't answer my question, my question is about the logical meaning of the two terms.

Upvotes: 7

Views: 1067

Answers (2)

padawin
padawin

Reputation: 4476

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)

Upvotes: 11

Romain Valeri
Romain Valeri

Reputation: 21938

In short

"parents" means the direct parents only, i.e. the commits whose SHA-1 is explicitly stated in a given commit's definition.

"ancestors" refers to a commit's parents and their parents, recursively.

Upvotes: 2

Related Questions