Liu Yubao <yubao.liu@xxxxxxxxx> writes: > I have heard git treats all parents equally in a merge operation, so I > am curious how git decides which parent is HEAD^1. The first parent you see when you do "git cat-file commit HEAD" is the HEAD^1, the second one is HEAD^2, etc. With typical Porcelains (including git-core), when you make a true merge by pulling another branch while on one branch, the tip of the branch you were on when you initiated the merge becomes the HEAD^1 of the resulting merge commit. However, that does not mean HEAD^1 is any special in the global history. It is only locally special when viewed by you who did the merge, and only immediately after you made the merge. After a while, even you yourself would feel less special about HEAD^1. Imagine the following scenario. . You fork off from Linus's tip, and you do a great work on the kernel for a while. o---o---o---o Liu / ---o Linus . Linus's tip progresses, and there are semantically some overlapping changes; you merge from Linus to make sure your great work still works with the updated upstream. This merge commit (marked '*' in the picture below) has _your_ last change as HEAD^1 and Linus's tip as HEAD^2. o---o---o---o---* Liu / / ---o---o---o---o---o Linus . It still works great and you let Linus know about your great work. He likes it and pulls from you. At this point, the revision history would still look like this: o---o---o---o---* Liu = Linus / / ---o---o---o---o---o That is, the DAG did not change since you pulled from Linus. The only thing that changed was that Linus's tip now points at the merge commit _you_ made. Then Linus keeps working, building commits on top of that merge. Liu o---o---o---o---*---o---o---o---o Linus / / ---o---o---o---o---o Now, we can say two things about this history. If you view the development community "centered around Linus", then when somebody looks back the history from Linus's tip, whatever great work you did, that is merely "one of the many contributions from many people". The "mainline" from this point of view is still "what Linus saw at each point as the tip of his development track", and among the commits you made (the ones between the fork point and '*' in the above picture), the last one, the merge you made was the only one that was once the tip of Linus; everything else was "random work that happend in a side branch". But HEAD^1 is not special if you wanted to have this view. In massively parallel and distributed development, whose track of development is "mainline" is not absolute, and it all depends on what you are interested in when you do the archaeology. Let's say that your work on the side branch was in one specific area (say, a device driver work for product X), and nobody else's work in that area appeared on Linus's development track since you forked until your work was merged. To somebody who is digging from Linus's tip in order to find out how that driver evolved, your side branch is much more important than what happened on Linus's branch (which everybody would loosely say _the_ "mainline"). On the other hand, when somebody is interested in some other area that was worked on in Linus's development track while your work was done in the side branch, following your development track is not interesting; and the person who is interested in this "other area" could be you. In that case, you would want to follow Linus's development track. What's mainline is _not_ important, and which parent is first is even less so. It solely depends on what you are looking for which branch matters more. Putting too much weight on the difference between HEAD^1 vs HEAD^2 statically does not make any sense. Reflecting this view of history, git log and other history traversal commands treat merge parents more or less equally, and _how_ you ask your question affects what branches are primarily followed. For example, if somebody is interested in your device driver work, this command: git log -- drivers/liu-s-device/ would follow your side branch. On the other hand, git log -- fs/ would follow Linus's development track while you were forked, if you did not do any fs/ work while on that side branch and Linus's development track had works in that area, _despite_ the merge you gave Linus has your development track as its first parent. - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html