Git: How to list commits on a merged branch?
Asked Answered
P

2

9

This is the inverse of how to list commits on a branch but not merged branches, so I'll ask it in the same format. Let's say my git commit history looks like this:

A---B---C---D---E---F master
     \         /
      X---Y---Z topic

How do I list the commits on the topic branch -- that is, X, Y, and Z? Note that simply doing git log topic won't work -- that will return commits A and B as well.

I had thought I could run git merge-base topic master to find B, and then do git log B..Z to get these commits. Unfortunately, git merge-base topic master returns Z, not B, which makes sense in retrospect -- since Z is already merged to master, the first commit between topic and master that shares history is Z.

Pion answered 7/5, 2014 at 14:8 Comment(1)
possible duplicate of Using Git, show all commits that are in one branch, but not the other(s)Changeless
L
5

If you only merged topic to master once, and you know that you merged topic into master in merge commit E, you can simply use the <rev>^-<n> revision syntax:

git log E^-

If you don't remember the hash of commit E and want an easy way to find it, based on the name of your branch (topic), you can use one of the answers in the question "Find merge commit which include a specific commit". I personnally like git when-merged:

git when-merged topic

Putting it all together:

git log $(git when-merged -c topic)^-

If you merged topic several times to master, then the syntax above will only list the commits that were merged in the most recent merge commit. In that case, you can use rocketraman's mergedtopiclg alias

git mergedtopiclg $(git when-merged -c topic)

For completeness this alias is configured as

    mergedtopiclg = !sh -c \"git lg $(git oldest-ancestor $1^2 ${2:-master})..$1^2\" -
    # The oldest ancestor between an integration branch (by default, master) and a topic branch (by default HEAD)
    # e.g. git oldest-ancestor master ai/topic
    # See https://mcmap.net/q/12053/-finding-a-branch-point-with-git
    oldest-ancestor = !bash -c 'diff --old-line-format= --new-line-format= <(git rev-list --first-parent \"${1:-master}\") <(git rev-list --first-parent \"${2:-HEAD}\") | head -1' -
Lourdeslourie answered 27/1, 2021 at 22:44 Comment(0)
I
4

You can use the following command:

git log topic --not $(git rev-list master ^topic --merges | tail -1)^

git rev-list master ^topic --merges returns the SHA-1 keys for all merge commits from master to topic; since it's possible that there are multiple merge commits I use tail -1 to just get the last merge commit which is the merge commit of master and topic.

Then we log all commits for topic while omiting all commits for the first parent of the merge commit (--not <merge-commit>^).

To use this command effectively I would define an alias as follows:

git config --global alias.<alias-name> '!f() { git log $1 --not $(git rev-list $2 ^$1 --merges | tail -1)^; }; f'

Which then can be used like this git <alias-name> topic master.


Just for your information:
In my git version (1.9.0) it would also work if you omit tail but I thought it would be cleaner to only return the relevant SHA-1 key.

Iconoduly answered 8/5, 2014 at 7:53 Comment(4)
This doesn't seem to work at all -- it gets me a lot of extra commits.Pion
@Pion it works perfectly fine for me. Can you provide me with your in- and output?Iconoduly
@SaschaWolf Would it be a way to get same result without cloning repository?Nolen
@SunggukLim What exactly do you mean? Do you mean you want to perform this for a remote repository such as one on GitHub?Iconoduly

© 2022 - 2024 — McMap. All rights reserved.