1

I'm trying to determine the frequency with which master is merged into a specific release branch. So, I want to know the history of all merge-bases. Is there a way to list all of the merges that have happened between two branches?

fuzzybear3965
  • 243
  • 5
  • 15
  • https://stackoverflow.com/a/24762903/7976758 `git log --merges` Found in https://stackoverflow.com/search?q=%5Bgit%5D+list+merges – phd Dec 22 '21 at 12:20
  • That's close, but doing `git log --merges` on branch `A` doesn't show me which merge commits are a result of merging in branch `B`. I want to see something like "all merge commits in A from B". – fuzzybear3965 Dec 22 '21 at 12:57
  • 1
    It's hardly possible — Git doesn't really remember to what branch a commit belonged in the past. Branches are just *current* pointers to commits. You can try to improve the list filtering it by commit message; it's only a guess, not a solution. Try `git log --merges --grep="Merge branch 'B'"` – phd Dec 22 '21 at 13:27
  • I agree. A branch is merely a temporary name for one commit. You don't merge branches; you merge _commits_. The concept presupposed by the question is meaningless. – matt Dec 22 '21 at 13:28
  • @phd Unfortunately `--grep` won't work as the merge commit messages don't include information about the merge operation (the commit message will be inherited automatically if there is no conflict). – fuzzybear3965 Dec 22 '21 at 13:29
  • 1
    The point is that it is your job to mark the merge commit in a searchable way if your plan is to do this kind of search later. You can use commit messages, tags, whatever. But only a human knows what you are looking for here; Git doesn't. – matt Dec 22 '21 at 13:31
  • @matt I understand what you mean - but, please try to be a little flexible with language. It's normal to say "merge one branch into the other", even if one means "merge the commits of one branch after a common ancestor into the history of the other branch, starting from that common ancestor". Let's say it this way, I want a list of those commits in one branch, call it A, which also exist in another branch, call it B, such that each of those commits has more than one parent. – fuzzybear3965 Dec 22 '21 at 13:31
  • @matt git knows which commit hashes are common between two branches and which commits have more than one parent. – fuzzybear3965 Dec 22 '21 at 13:33
  • I know what is normal to _say_. But what we say about Git is often very misleading (such as the mistaken notion that a commit is "on" a branch). I'm telling you what Git actually _is_. – matt Dec 22 '21 at 13:33
  • Fair enough. Can you provide a solution to the following: I want a list of those commits in one branch, call it A, which also exist in another branch, call it B, such that each of those commits has more than one parent. – fuzzybear3965 Dec 22 '21 at 13:34
  • Or, roughly equivalently, can you provide a way to list a history of all merge-bases? I.e., if `git merge-base B` while on branch `A` returns abcdef1234 then I also want the result of `git merge-base abcdef1234~1`, and so on)? – fuzzybear3965 Dec 22 '21 at 13:36

1 Answers1

1

You can tell git log to output the commit hashes of the parent commits for each displayed commit :

git log --format="%p" --first-parent --merges release

# to get only second parents, just use awk or cut :
git log --format="%p" --first-parent --merges release | awk '{ print $2 }'

You can now check one by one whether each commit is part of branch master, perhaps using :

git rev-list --first-parent master | grep $sha

("the first parents of a branch" is the closest thing you will get to a history of that branch)


using a one liner :

git rev-list --format="%P" --first-parent --merges release | awk '{ print $2 }' |\
    grep -F -f <(git rev-list --first-parent master)

or adapting your usage of "uniq" in your comments:

(git rev-list --format="%P" --first-parent --merges release | awk '{ print $2 }';\
  git rev-list --first-parent master) | sort | uniq -d
LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • What do you think of the below? `git checkout && echo "$(git --no-pager rev-list --merges HEAD)" "$(git --no-pager rev-list --merges master)" | uniq` – fuzzybear3965 Dec 22 '21 at 14:08
  • 1
    the merges you are looking for are part of `release` history, but not part of `master` history, `git rev-list --merges master` will not list commits you are interested in. – LeGEC Dec 22 '21 at 14:14
  • I actually want to only print those that are duplicated, and `uniq` won't work unless I sort, first, so `git checkout && echo "$(git --no-pager rev-list --merges HEAD)" "$(git --no-pager rev-list --merges master)" | sort | uniq -d` is better. – fuzzybear3965 Dec 22 '21 at 14:14
  • 1
    updated my answer : realized you would only look for merges in `release` *in the first parent history* – LeGEC Dec 22 '21 at 14:14
  • "the merges you are looking for are part of release history, but not part of master history". The commits I'm looking for _need_ to be a part of history. I want to list commits that "came from" the master branch (`git merge master` when on ) – fuzzybear3965 Dec 22 '21 at 14:15
  • 1
    you may do your `uniq` trick by combining the output of my first command, and `git log --first-parent --format="%h" master` (when you specify `--format`, `git rev-list` and `git log` are basically synonyms) – LeGEC Dec 22 '21 at 14:16
  • your first one-liner yields empty results. Your second one-liner (`uniq`) looks like it could be right. – fuzzybear3965 Dec 22 '21 at 14:22
  • 1
    I fixed the options to `grep` : I had forgotten the `-f` (read patterns from a file). The `-F` (interpret all patterns as fixed strings) is only here to speed up things. – LeGEC Dec 22 '21 at 14:28
  • Ah, okay. We're getting closer, but now we have a consistency problem. I think your one-liner is not catching all of the possible common commits in the branch and master. Your one-liner: `git rev-list --format="%P" --first-parent --merges HEAD | awk '{ print $2 }' |\ grep -F -f <(git rev-list --first-parent master) | wc -l` returns 384 `echo "$(git --no-pager rev-list --merges HEAD)" "$(git --no-pager rev-list --merges master)" | sort | uniq -d | wc -l` returns 83243 (closer to what I expect since `master` has ~350,000 commits and merges a few times per day. – fuzzybear3965 Dec 22 '21 at 14:31
  • that kind of numbers ? :D To debug : replace raw `git rev-list` output with something like `--graph --format="%h %s - %p"` (`%h %s` will give short hash + one line message for each commit), and check if the list of commits you see in each case (`git rev-list --first-parent --merges release` and `git rev-list --first-parent master`) matches what you expect -- you can compare it with what you see in some other viewer of your repository. – LeGEC Dec 22 '21 at 16:51