En supposant que le référentiel distant possède une copie du développement branche de (votre description initiale la décrit dans un référentiel local, mais il semble qu'elle existe également dans la télécommande), vous devriez être en mesure de réaliser ce que je pense que vous voulez, mais l'approche est un peu différent de ce que vous avez imaginé.
L'histoire de Git est basée sur un DAG de commits. Les branches (et les «refs» en général) ne sont que des étiquettes transitoires qui pointent vers des validations spécifiques dans le DAG de validation en constante augmentation. En tant que tel, la relation entre les branches peut varier dans le temps, mais pas la relation entre les validations.
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
Il semble être baz
basé sur (une ancienne version de) bar
? Mais que se passe-t-il si nous supprimons bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Maintenant, on dirait qu'il baz
est basé sur foo
. Mais l'ascendance de baz
n'a pas changé, nous venons de supprimer une étiquette (et la validation qui en résulte). Et si nous ajoutons une nouvelle étiquette à 4
?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
Maintenant, on dirait qu'il baz
est basé sur quux
. Pourtant, l'ascendance n'a pas changé, seules les étiquettes ont changé.
Si, cependant, nous demandions "est-ce que commettre est 6
un descendant de commit 3
?" (en supposant 3
et 6
sont des noms de validation SHA-1 complets), la réponse serait «oui», que les étiquettes bar
et quux
soient présentes ou non.
Ainsi, vous pouvez poser des questions comme «la validation poussée est-elle un descendant de la pointe actuelle de la branche de développement ?», Mais vous ne pouvez pas poser de manière fiable «quelle est la branche parente de la validation poussée?».
Une question principalement fiable qui semble se rapprocher de ce que vous voulez est:
Pour tous les ancêtres du commit poussé (à l'exception de la pointe actuelle de develop et de ses ancêtres), qui ont la pointe actuelle de develop comme parent:
- existe-t-il au moins un tel commit?
- y a-t-il des commits monoparentaux?
Qui pourrait être implémenté comme:
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_children_of_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
,) echo "must descend from tip of '$basename'"
exit 1 ;;
,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
exit 1 ;;
,*) exit 0 ;;
esac
Cela couvrira une partie de ce que vous souhaitez restreindre, mais peut-être pas tout.
Pour référence, voici un exemple d'historique étendu:
A master
\
\ o-----J
\ / \
\ | o---K---L
\ |/
C--------------D develop
\ |\
F---G---H | F'--G'--H'
| |\
| | o---o---o---N
\ \ \ \
\ \ o---o---P
\ \
R---S
Le code ci - dessus peut être utilisé pour rejeter H
et S
tout en acceptant H'
, J
, K
ou N
, mais il serait aussi accepter L
et P
(ils impliquent des fusions, mais ils ne se confondent pas la pointe de développer ).
Pour refuser également L
et P
, vous pouvez modifier la question et demander
Pour tous les ancêtres du commit poussé (à l'exception de la pointe actuelle de develop et de ses ancêtres):
- y a-t-il des engagements avec deux parents?
- sinon, au moins un de ces commit a-t-il la pointe actuelle de développer son (seul) parent?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_commits_beyond_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
*\ *) echo "must not push merge commits (rebase instead)"
exit 1 ;;
*"$baserev"*) exit 0 ;;
*) echo "must descend from tip of '$basename'"
exit 1 ;;
esac