Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is --first-parent not the default for git show?

Tags:

git

I'm sure this question will be closed as opinion-based but there's nowhere else so ask it so here goes...

I'm trying to view the history of my branch which includes merge commits (specifically what changed) and I found a very useful post here git show of a merge commit that tells me to use git show --first-parent

What's still confusing me is why --first-parent isn't the default for git show, or even why any other behavior is useful at all. If I'm looking in my history on a specific branch at a specific commit, the only thing I ever want to know is the difference between that version of the branch and the previous one.

Of course it could be that git commands are written for the convenience of the authors who don't give a shit what their end users actually want, but I suspect that there is a proper reason. Could someone explain why, with a better knowledge of git, I might not want to use --first-parent all the time.

like image 362
Andy Avatar asked Apr 10 '18 12:04

Andy


1 Answers

Well, I guess it's worse than you think, because the behavior of --first-parent is not the behavior you describe as the "only useful" behavior. It often works out to be the same, but that depends on the branch/merge workflow used with the repo.

(None of which has anything to do with the "convenience of the authors", who are quite capable of making an option the default if it actually made sense to do so.)

The "first parent" does not mean "the parent from the branch I'm on". In fact, nothing in git means "the parent from the branch I'm on", because in git the relationship between branches and commits doesn't work that way. If a merge is reachable from a branch, so are all of its parents. It may typically be true that one of those parents was, at one time, pointed to directly by the current branch. That is something git neither knows nor cares about.

"First parent" just means "the commit that was recorded first in the merge's parent list", which has nothing to do with the current state of refs.

Now, if you use the porcelain command git merge to produce a merge commit, then whatever is currently checked out will be recorded as the first parent. And if you're not in detached head state when you do this - meaning you have a branch checked out - then that branch will advance to the merge commit. So it often works out that you're reading a branches history, and you pass through a number of merge commits that were merges "into" the current branch.

But suppose right after merging branch2 into master you then say

git checkout branch2
git merge master

which will fast-forward branch2 onto the merge commit. Now, with branch2 still checked out

git show --first-parent

and you'll see the parent that "came from" master even though that's not the branch you have checked out.

And you can say "but in my workflow, I never do that, so my assumption holds". Well, in that case your assumption holds for you. But git wasn't written just for you, and it doesn't make assumptions that everyone works the way you happen to work.

The purpose of git show is to give information about the specified commit. The purpose of --first-parent - in this and numerous other commands - is to limit that information in cases where looking only at the first parent of a merge makes the picture more clear. That limiting of information needs to be requested so that git doesn't apply it when it would make the picture less clear.

But ok, even though --first-parent doesn't mean quite what you've said you want shows default behavior to be, why not make show behave the way you describe? Well, because the way git stores data, there's no way to identify "the parent from my current branch", and if you changed the way the data is stored to make that possible, it would impose new limitations on git that are bigger problems than what you're trying to solve.

like image 184
Mark Adelsberger Avatar answered Nov 15 '22 08:11

Mark Adelsberger