As part of a Jenkins Pipeline build system, I need to find out the specific commit SHA of the closest ancestor of any branch, be it master or any other branch. Visually, with arrows pointing to the desired commit compared to the one being analyzed:
As in (1), the ancestor is master (black line), but it is not the immediately preceding commit, which was already part of the branch. In (6), the desired commit is part of the branch labeled as 'Dev'.
In my scenario, this will only be executed when triggered by git pushes, so we could at least assume that the current branch in not merged to any other yet (hopefully).
I'm not experienced with Git, so I tried to piece something together, but so far nothing worked as expected. Anybody have a suggestion for this?
Failed ideas
execute
git rev-list HEAD ^list-all-branches-but-the-current-one
, get the oldest commit and then get it's immediate ancestor, but this fails because my current branch may be branched, so the commits that belong to both would be removed, and I'd end up with the SHA for where my branch was branched, not where it branched from;This other SO answer gives a nice command to find the ancestor of a branch compared to another:
diff --old-line-format= --new-line-format= <(git rev-list --first-parent master) <(git rev-list --first-parent HEAD) | head -1
, but the problem with this is that I still don't know against which branch to compare, as it won't be always master.
Update 1
I've been playing a bit more with alternatives, and I reached this modified version of the one in the comments of this SO answer:
git rev-parse "$(git show-branch | sed "s/].*//" | grep "\*" | tail -n 1 | sed 's/.*\[\(.*\)/\1/')"~1
It uses the visual display of the branches, doing the following steps:
- Show the branches;
- Removes everything after the first
]
, which is surrounding commit references; - Keeps only lines containing
*
, which is used to mark your current branch; - Takes only the last line (oldest);
- Removes everything up to the
[
, leaving only the commit reference; - Gets the commit preceding the one obtained in the last step, the branching point.
The drawbacks that I could confirm:
- Do not work if you checkout a commit hash, you need to check out a branch;
- Consequently, the branch need to exist (you can't do it in any point of the tree);
- (not totally sure) if you do it in a branch of another branch that is now deleted, it goes all the way to the point where the now deleted branch branched from its parent.
According to my tests, it seems to work and may be sufficient for my scenario. Any evaluations?