I'm learning about relative commit references and trying to understand the following git log --oneline --graph
output provided in a lesson.
In the lesson it says that given HEAD points to the 9ec05ca
commit, HEAD^^^ (meaning the great-grandparent commit) is the 0c5975a
commit. But it seems to me 4c9749e
should be the great grandparent, if each SHA is a direct descendant of the one below it. Any clarification appreciated.
Commit can have more than one parent. ^ 1 means first parent. ^2 means second parent and do on. Just ^ defaults to ^1 which is first parent.
Similarly ~ give access to traverse up for an ancestor. For example if you want 3 generation up ~3. If you want 7th last commit in same branch favouring first parent while traversing.
Any merge will have two parents with merge to branch becoming first parent. Merge from branch becoming second parent.
setia_'s answer remains the most appropriate but your question is meaningful because a git history can be considered from two distinct perspectives: either you totally view it as a (mathematical) graph in which parent's order is supposed to be non significant, OR you consider a merge operation as the integration of an external branch into a common trunk (i.e. your current branch, very often "master"). This is also the assumption made by
git merge
.This is important not only because browsing an exponentially growing tree rapidly becomes a pain, but also because having a branch "master" that contains a finished product and integrating external submissions is a model followed by many workflows.
Since both these points of view are valid, they cause
--first-parent
to be a frequently used option, though not a main command nor a default behavior.For example, browsing the Linux kernel main repository (for which Git was first designed) with a simple
git log --graph
can take up to one minute before displaying something, butgit log --graph --first-parent
will show you the main branch and let you observe that it's mainly composed of merges, with occasional direct commits.Another thing one have to keep it mind is that you can ask to have your commits displayed by chronological order using
--date-order
or topological order with--topo-order
. Let's assume you have two distinct branches and alternatively commit to the one or the other before eventually merging them. Depending on the order, the resulting graph would look like one of these :All commits remain on their respective line but the latter is a depth-first search. And since
git log
(so doesgit rev-list
) displays a collection of pre-gathered revisions, this order will be the same whether you're using--graph
or displaying them as a flat list (actually, if not specified,git log
use reverse chronological order by default, and topological one when using--graph
).Because of that, you can't simply rely on the first row to decide which parent to choose.
This can also cause some older commits to appear before the new ones, which can be very confusing when beginning with Git, and give you the impression that your work has disappeared (until it comes to one's mind to perform a search, then retrieve it buried somewhere in history).