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.
Best Answer
Assuming that the remote repository has a copy of the develop branch (your initial description describes it in a local repository, but it sounds like it also exists in the remote), you should be able to achieve what I think you want, but the approach is a bit different from what you have envisioned.
Git’s history is based on a DAG of commits. Branches (and “refs” in general) are just transient labels that point to specific commits in the continually growing commit DAG. As such, the relationship between branches can vary over time, but the relationship between commits does not.
It looks like
baz
is based on (an old version of)bar
? But what if we deletebar
?Now it looks like
baz
is based onfoo
. But the ancestry ofbaz
did not change. We just removed a label (and the resulting dangling commit). And what if we add a new label at4
?Now it looks like
baz
is based onquux
. Still, the ancestry did not change, only the labels changed.If, however, we were asking “is commit
6
a descendent of commit3
?” (assuming3
and6
are full SHA-1 commit names), then the answer would be “yes”, whether thebar
andquux
labels are present or not.So, you could ask questions like “is the pushed commit a descendent of the current tip of the develop branch?”, but you can not reliably ask “what is the parent branch of the pushed commit?”.
A mostly reliable question that seems to get close to what you want is:
Which could be implemented as:
This will cover some of what you want restricted, but maybe not everything.
For reference, here is an extended example history:
The above code could be used to reject
H
andS
while acceptingH'
,J
,K
, orN
, but it would also acceptL
andP
(they involve merges, but they do not merge the tip of develop).To also reject
L
andP
, you can change the question and ask