0

Let's say there are two branches in hand:

master:

0--1--2 

dev:

0--1--3 

So we merge dev into master, and we end up with the merge commit 4 with the two parent commits 2 and 3:

0--1----2---4 \--3---/ 

Now, if we get rid of the merge commit via git reset --soft head~1, we end up with the following log:

0--1--2 

Question is: why does git decide to remove commit 3 but not commit 2?

2 Answers 2

1

When you ask git for git reset --soft HEAD~1, you (none other) are asking git to place the branch pointer on a given revision (HEAD~1) which, in this case, ends up being revision 3. Probably, you had merged revision 2 standing on top of revision 3 so in the revision the first parent would be 3 and that's why HEAD~1 will point to revision 3.

If you ask git for git reset --soft 2 (provide revision ID for revision 2), you will end up with 0 - 1 - 2. It's not git who decides, it's you by running that command.

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

6 Comments

Correct me if I'm wrong, HEAD~1 means parent of the head. In that case head has two parents. So which one does HEAD~1 point to?
~ will always take the first of the n parents of a merge commit as defined on the revision. You can see them with $ git show --summary some-revision. In case you want to define a different parent from the first, you can do so with the ^ operator instead.
Just a tip: If you try to merge revision 2 from revision 3, you will get a revision with revision 3 as the first parent. But if you do it the opposite way (merge revision 3 from revision 2) you will end up with a revision that has first parent set to 2 and the second set to 3.
Thanks. Also, I didn't know about git reset --soft <commit-sha>.
Just one more thing: In that case a parent becomes invisible in the log. Does it mean it's been removed, or it's still accessible somehow?
|
1

Something's fishy in your example; I can't reproduce it. But for the git background, which should prove sufficient to see what's going on yourself. From Git Book:

You can also specify a number after the ^ – for example, d921970^2 means “the second parent of d921970.” This syntax is useful only for merge commits, which have more than one parent. The first parent is the branch you were on when you merged, and the second is the commit on the branch that you merged in

and

The other main ancestry specification is the ~ (tilde). This also refers to the first parent, so HEAD~ and HEAD^ are equivalent. The difference becomes apparent when you specify a number. HEAD~2 means “the first parent of the first parent,” or “the grandparent” — it traverses the first parents the number of times you specify.

Thus:

In that case head has two parents. So which one does HEAD~1 point to?

It refers to the first parent of HEAD - i.e. the branch you were on when you merged. There is no way to access the second parent (the merged-in branch) by the tilde syntax alone.

1 Comment

"the first parent of HEAD - i.e. the branch you were on when you merged" was very enlightening.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.