3

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:

Some Git history I found

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:

  1. Show the branches;
  2. Removes everything after the first ], which is surrounding commit references;
  3. Keeps only lines containing *, which is used to mark your current branch;
  4. Takes only the last line (oldest);
  5. Removes everything up to the [, leaving only the commit reference;
  6. Gets the commit preceding the one obtained in the last step, the branching point.

The drawbacks that I could confirm:

  1. Do not work if you checkout a commit hash, you need to check out a branch;
  2. Consequently, the branch need to exist (you can't do it in any point of the tree);
  3. (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?

Community
  • 1
  • 1
mdrg
  • 3,242
  • 2
  • 22
  • 44
  • So you want the first commit going backwards that can be reached from another branch? – Mad Physicist Sep 20 '16 at 17:55
  • 1
    Barring merge commits to/from another branch of course. – Mad Physicist Sep 20 '16 at 17:57
  • @MadPhysicist yes, that's another way to explain it. I guess the way you're putting it is based on the assumption that the branch is unmerged... it wouldn't work backwards with old merged branches (like the image), but if it simplifies the answer, it is fine, it should work in my scenario. – mdrg Sep 21 '16 at 08:42
  • I am not sure why it wouldn't work with the old branches that get merged it. They get skipped in the search algorithm I am proposing. – Mad Physicist Sep 21 '16 at 16:04
  • @MadPhysicist is this you are proposing? `git branch -r --contains HEAD~X | wc -l` with X starting from 0 and increasing until the output is larger than 1, and then `git rev-parse HEAD~FINAL_X` to get the commit hash. I tested manually, and it will reach the first point the current branch splits, be its origin or a new branch of it. It ends up being pretty much like my first 'failed idea'. Is this what you're suggesting or something better? Thanks! – mdrg Sep 22 '16 at 08:58
  • To be honest, I wasn't suggesting anything just yet, just trying to wrap my head around what you are trying to do exactly. – Mad Physicist Sep 22 '16 at 15:56
  • Possible duplicate of [Finding a branch point with Git?](http://stackoverflow.com/questions/1527234/finding-a-branch-point-with-git) – Joe Sep 24 '16 at 14:41
  • @Joe I already linked to that post in my second "failed idea" above. In that scenario, it is a comparison to `master`, and I want to know where it branches from any branch which I don't know the name, hence that answer is not enough for me. It works nice for two know branches, not if you know only your current branch. – mdrg Sep 25 '16 at 11:17

0 Answers0