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?
Asked
Active
Viewed 279 times
1
-
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
-
1It'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
-
1The 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 Answers
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 -
1the 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 -
1updated 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) -
1you 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
-
1I 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 – fuzzybear3965 Dec 22 '21 at 14:31merges a few times per day. -
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