0

I have on the surface what appears to be a simple issue to handle but under the covers things get sticky quick. I am still at the straw man stage so there isn't any functional code to share.

The Desired Behavior:
We attach diffs for commits to our bug tracking application using bug IDs contained within the commit comments. The attachment occurs using a script called from an post-recieve hook in Git, and change-merged in Gerrit.

The Problem:
When a new branch is initially pushed the first commits $oldrev value is 00000000000000000. This occurs for every new branch and in Gerrit it occurs for every branch you push to HEAD:refs/for/$branch. This results in the diff not being attached for the first commit of a new branch or in the case of Gerrit, diffs do not attach for every first commit within every code review.

My current proposed fix is complex and ugly. I was hoping that someone might know of a more elegant way to determine the originating SHA for a given branch:

Step1: Determine the parent branch of the current branch.

I unabashedly stole the commands to retrieve a parent branch from this GitHub gist: https://gist.github.com/joechrysler/6073741

my $branch = git rev-parse --abbrev-ref HEAD; my $parent = git show-branch -a 2>/dev/null | grep '\*' | grep -v "$branch" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//';

Those two shell commands pull in the parent branch nicely and give me no output if the branch is parentless so that makes for an easy scripted check for parentage. The problem is that the process falls apart when the branch was created off of a tag that was generated from a branch that no longer exists using a SHA that no other branch references. In Git terms that means the new branch is parentless so logically all is well but in practice I still want to diff the changes from the SHA that the branch was pulled from.

Step2: (Assuming there is a parent branch)

Run Git cherry to pull only the commits associated with my branch, excluding the commits from parent:

my $parent = git cherry -v $parent $refs;

The commit order is reversed from normal git log output so the oldest SHA is at the top of the list allowing me to pull the first value that contains letters and numbers from an array. Pull that first committed SHA and determine it's parent using a simple git log command:

my @oldrevs=git log -n 2 --pretty=format:%H $first_sha;

Final Steps: Remove all entries in the @oldrev array that do not contain letters or numbers using a for loop and set

$oldrev = $oldrevs[-1];

since git log output shows the oldest commit last. This gets rid of the null SHA value for the purposes of diff attachment in 99% of cases but it's a lot of hoops to jump through. Can anyone suggest a cleaner method that might also be able to pull in the originating SHA for a branch generated from a tag that references a commit no longer references in any branches within the repo?

JonE
  • 1
  • Because [Git branches don't record their parents](https://stackoverflow.com/q/3161204/1256452), whatever you do is going to be messy—unless, that is, it's to require that the person who makes a new branch record, in its commit message(s), something that locates the commit(s) against which to compare. Another possibility, in the git hook, is to use `--not --all` to identify commits reachable from the new name that are not reachable from any existing name, but this fails badly if two branches are created in the same `git push`. – torek Jan 05 '18 at 17:51
  • Similar discussion here https://stackoverflow.com/questions/1527234/finding-a-branch-point-with-git – Chris F Feb 23 '18 at 22:03

0 Answers0