0

I'm trying to get the first merge commit for a given SHA. I tried the script from here: https://stackoverflow.com/a/30998048 (has a command for git find-merge) but unfortunately it doesn't do quite what I need.

The situation that I have is that I had a fix branch off of a release branch that was then merged into the release branch. From there the release branch was merged into main. So my tree looked like this:

main - - - - - - - - - - - - -
                             / (merge #2)
release - - - - - - - - - - /
\              /  (merge #1)
  fix - - - - /

However using the git find-merge (fix SHA) (merge #2 SHA) with the fix branch SHA gives the SHA of merge #2 instead of merge #1. I want to know the SHA of the first time a commit was merged. Does anyone have any git terminal command to do so?

A note that if I use git find-merge (fix SHA) (merge #2 SHA - 1) and give it the SHA of the fix commit and the SHA 1 before merge #2 it works, however if there was a merge #3 in there I think that is the SHA I would get back instead.

DMCApps
  • 2,110
  • 4
  • 20
  • 36

2 Answers2

0

The command from the answer for find-merge uses the branch as the second argument. In git, branches are just a pointer to a particular commit, using a branch name is just like using the SHA of the latest commit for that particular branch.

So you are basically running git find-merge <fix sha> main, so it finding <sha merge 2> would be correct since that is when your fix sha was merged into that branch.

The reason that <merge #2 sha - 1> gives you the answer that you are looking for is because you are on the one of two commits - the latest commit on main before merge #2 happened (which would result in nothing) or the last commit on the release branch before it was merged. The second case is basically git find-merge <fix sha> release and would result in the sha you are looking for.

In order to find the merge commit that you are looking for, you are going to have to iteratively check each merge commit to see if there is another one between it and the sha that you want until there isn't a merge commit between them.

UPDATE

Here is a basic bash script that should trace back merges to the first branch that was merged into the target branch. My repo doesn't have that much branching so the testing is very limited.

#!/bin/bash

com=$1
branch=$2

mergeCommit = git find-merge $1 $2

while [ mergeCommit ];
do
    echo mergeCommit
    mergeCommit = git find-merge $1 $mergeCommit~
done;

Basically, this takes the merge commit found by find-merge and takes the previous commit and tries to find merge commit between that and the target commit. Repeating until there are no merges left between the target and merge commit find.

Schleis
  • 41,516
  • 7
  • 68
  • 87
  • Is there a way to achieve `git find-merge release` when the local and remote `release` branch is gone? I guess that is in essence the `main - 1` SHA that I tested and it worked for. However that isn't a solution as if the `fix` is merged to `release` that is merged to `develop` that is merged to `main` then that `main - 1` would just give back the merge to `develop` – DMCApps Feb 10 '23 at 15:52
  • A branch isn't ever gone exactly. The commits that made up that that branch will always exist. If your commits are using the generated message then you would be able to use that to trace the name of the branches when you examine the merge commit. Commits contain the sha that they are the child of (merge commits contain 2) a branch is just a floating alias to a commit. – Schleis Feb 10 '23 at 16:43
  • I understand theoretically how to do it, I do have some markings that I could look for in the commit messages to find out which merge it is associated with. I use a tag number in all my commits which is also in the branch name, so I could look up the merge commit by traversing from the current SHA to the next until I find that message. Can you update your answer with what command I could use to say Traverse from `SHA_A..SHA_B` and only get the message that contains say a variable `${TICKET_ID}` – DMCApps Feb 10 '23 at 17:00
0

Does this work for you?

SHA="your commit SHA" branch="release" git log --merges --ancestry-path $SHA^..$branch

tested with these commands:

git checkout -b release  # from master
git checkout -b fix
git commit --allow-empty -m 'commit from fix'
git log  # get the SHA of this commit

git checkout release
git merge fix --no-ff

git checkout master
git merge release --no-ff
Roelof
  • 63
  • 8
  • I don't think this works as I clean up all my branches as they are merged so non are remaining to use in the `branch` variable name – DMCApps Feb 10 '23 at 15:55
  • Ah, yes, that makes it more difficult, it could still work; if the deleted branch has been merged, just replace the `$branch` variable with master or HEAD, but it will no longer be clear which branch it came from – Roelof Feb 10 '23 at 22:22