Zakładając, że zdalne repozytorium posiada kopię rozwinięcia gałęzi (początkowy opis opisuje go w lokalnym repozytorium, ale to brzmi jak również istnieje w pilocie), powinieneś być w stanie osiągnąć to, co myślę, że chcesz, ale podejście różni się nieco od tego, co sobie wyobrażałeś.
Historia Git opiera się na DAG zatwierdzeń. Gałęzie (i ogólnie „referencje”) są tylko przejściowymi etykietami, które wskazują na określone zatwierdzenia w stale rosnącym DAG zatwierdzania. W związku z tym relacje między oddziałami mogą się zmieniać w czasie, ale związek między zatwierdzeniami się nie zmienia.
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
Wygląda na to, że baz
jest oparty na (starej wersji) bar
? Ale co jeśli usuniemy bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Teraz wygląda na to, że baz
jest oparty na foo
. Ale pochodzenie baz
się nie zmieniło, po prostu usunęliśmy etykietę (i wynikające z tego zwisające zatwierdzenie). A jeśli dodamy nową etykietę w 4
?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
Teraz wygląda na to, że baz
jest oparty na quux
. Mimo to pochodzenie się nie zmieniło, zmieniły się tylko etykiety.
Gdybyśmy jednak pytali „czy popełnienie 6
potomka popełnienia 3
?” (zakładając 3
i 6
są to pełne nazwy zatwierdzeń SHA-1), wówczas odpowiedź brzmiałaby „tak”, niezależnie od tego, czy etykiety bar
i quux
są obecne, czy nie.
Można więc zadawać pytania typu „czy wypychany zatwierdzenie jest potomkiem aktualnej końcówki gałęzi rozwijania ?”, Ale nie można rzetelnie zadać pytania „jaka jest gałąź nadrzędna zatwierdzonego przekazu?”.
Najbardziej wiarygodne pytanie, które wydaje się zbliżać do tego, czego chcesz, to:
Dla wszystkich przodków wypychanego zatwierdzenia (wyłączając bieżącą wskazówkę dewelopera i jej przodków), którzy mają bieżącą wskazówkę rozwijania jako rodzic:
- czy istnieje przynajmniej jedno takie zatwierdzenie?
- czy wszystkie takie zatwierdzenia zatwierdzają osoby samotnie wychowujące dzieci?
Które można zaimplementować jako:
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
To obejmie część tego, co chcesz ograniczyć, ale może nie wszystko.
Dla odniesienia, oto rozszerzona przykładowa historia:
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
Powyższy kod można wykorzystać do odrzucenia H
i S
przyjmując H'
, J
, K
, lub N
, ale również zaakceptować L
i P
(obejmują one scala, ale nie połączyć końcówkę rozwijać ).
Aby odrzucić L
i P
, możesz zmienić pytanie i zadać
Dla wszystkich przodków wypchniętego zatwierdzenia (z wyjątkiem aktualnej końcówki develop i jego przodków):
- czy są jakieś zobowiązania z dwojgiem rodziców?
- jeśli nie, to czy przynajmniej jedno takie zatwierdzenie ma bieżącą wskazówkę dotyczącą rozwoju (jedynego) rodzica?
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