Let’s say I have the following local repository with a commit tree like this:
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
is my this is the latest stable release code, develop
is my this is the ‘next’ release code, and feature
is a new feature being prepared for develop
.
Using hooks, I want to be able to refuse pushes to feature
to my remote repository, unless commit f
is a direct descendant of develop
HEAD. I.e., the commit tree looks like this, because feature has been git rebase
on d
.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
So is it possible to:
- Identify the parent branch of
feature
?
- Identify the commit in parent branch which
f
is a descendant of?
From there I would check what HEAD of the parent branch is, and see if f
predecessor matches the parent branch HEAD, to determine if the feature needs to be rebased.
A rephrasal
Another way to phrase the question is “What is the nearest commit that resides on a branch other than the current branch, and which branch is that?”
A solution
You can find it with a little bit of command-line magic
git show-branch \
| sed "s/].*//" \
| grep "\*" \
| grep -v "$(git rev-parse --abbrev-ref HEAD)" \
| head -n1 \
| sed "s/^.*\[//"
With AWK:
git show-branch -a \
| grep '\*' \
| grep -v `git rev-parse --abbrev-ref HEAD` \
| head -n1 \
| sed 's/[^\[]*//' \
| awk 'match($0, /\[[a-zA-Z0-9\/-]+\]/) { print substr( $0, RSTART+1, RLENGTH-2 )}'
Here’s how it works:
- Display a textual history of all commits, including remote branches.
- Ancestors of the current commit are indicated by a star. Filter out everything else.
- Ignore all the commits in the current branch.
- The first result will be the nearest ancestor branch. Ignore the other results.
- Branch names are displayed [in brackets]. Ignore everything outside the brackets, and the brackets.
- Sometimes the branch name will include a
~#
or ^#
to indicate how many commits are between the referenced commit and the branch tip. We don’t care. Ignore them.
And the result
Running the above code on
A---B---D <-master
\
\
C---E---I <-develop
\
\
F---G---H <-topic
Will give you develop
if you run it from H and master
if you run it from I.
The code is available as a gist.