0

When you merge one branch into another, you get a commit that describes the merge. If we use neovim as an example, a4b96f2 is the commit introduced in a branch, and 6b7ece6 is the commit resulted from the merge.

What confuses me is that these two commits have the exact same content. How does that make sense? Also, If I reset the master to 1 commit back, by git reset HEAD~, both commits are cancelled. Why is that?

3
  • Are you asking why there is a different hash if the tree state is the same? Commented Mar 3, 2015 at 3:48
  • It would be nice if you linked to the commit rather than the project. Commented Mar 3, 2015 at 3:51
  • @CarlNorum yeah, I'm not sure what's the tree state you are referring to, but that could be what I'm asking. Commented Mar 3, 2015 at 3:57

2 Answers 2

3

The commit you're referring to is a merge commit. It's what happens when git can't do a fast-forward merge.

As to why you lose both commits when you do git reset HEAD~, that's explained pretty well here. Basically ref~ is shorthand for ref~1 and means the commit's first parent. That merge commit's first parent is (probably) on the branch it was merged to (not the branch it was merged from) so you no longer see both commits.

Consider this tree

 First parent | A -- B ---- D <--- You're here \ / C ^ Second parent 

Going back one commit to the first parent would put you here

 First parent <--- You're here | A -- B ---- D \ / C ^ Second parent 

Since you are now at commit B, neither commit D nor C are visible. The commits aren't canceled, they are just not visible from the commit you are on. You generally only see parent (past) commits of the commit you're on, not child (future) commits.

Sign up to request clarification or add additional context in comments.

4 Comments

"when git can't do a fast-forward merge" --- in that particular case git could FF for sure, but github did not do that intentionally.
"Neither commit D nor C are visible." --- why C is "not visible" actually? It's still there in the tree
@zerkms Updated my answer. It's in the tree, but it's not an ancestor of B so it shouldn't show up when you view the history (it's in the future, so to speak). I could also be misunderstanding how parents of commits are arranged.
It's probably a terminology confusion. OP uses "cancel" term even though the changesets are still there (they just don't know how to see them). But yes, now I see what you meant. And they are arranged exactly like that actually.
2

It's a result of merge that did not use Fast-Forward.

If no-ff flag is used what is happening is that git takes the 2 nodes: the current one and the other one and creates another node that has them both as parents.

How does that make sense?

It makes clear that the changeset came from somewhere else. Since otherwise it won't be possible to say if you actually did have permissions and committed to the main tree or your code was just pull-request'ed.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.