Предполагая, что удаленный репозиторий имеет копию ветви разработки (ваше первоначальное описание описывает ее в локальном репозитории, но похоже, что она также существует в удаленном), вы должны быть в состоянии достичь того, что я думаю, что вы хотите, но подход немного отличается от того, что вы предполагали.
История Git основана на DAG коммитов. Ветви (и вообще «ссылки») - это просто временные метки, которые указывают на конкретные коммиты в постоянно растущей DAG коммитов. Таким образом, отношения между ветвями могут меняться со временем, но отношения между фиксациями не изменяются.
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
Похоже на bazоснове (старой версии) bar? Но что если мы удалим bar?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Теперь, похоже, bazосновано на foo. Но происхождение bazне изменилось, мы просто удалили метку (и получившийся висячий коммит). А что если мы добавим новый ярлык на 4?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
Теперь, похоже, bazосновано на quux. И все же родословная не изменилась, изменились только ярлыки.
Если, однако, мы спрашиваем «является ли коммит 6потомком коммита 3?» (предполагая , что 3и 6полный SHA-1 совершают имена), то ответ будет «да», то ли barи quuxметки присутствуют или нет.
Таким образом, вы можете задать такие вопросы, как «является ли проталкиваемый коммит потомком текущего кончика ветви разработки ?», Но вы не можете с уверенностью спросить «какова родительская ветвь проталкиваемого коммита?».
Наиболее надежный вопрос, который, кажется, приближается к тому, что вы хотите:
Для всех предков выдвинутого коммита (за исключением текущего наконечника развертки и его предков), у которых текущий наконечник развития является родительским:
- существует хотя бы один такой коммит?
- все ли такие коммиты с одним родителем?
Который может быть реализован как:
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
Это покроет то, что вы хотите ограничить, но, возможно, не все.
Для справки, вот расширенный пример истории:
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
Приведенный выше код может быть использован для отклонения Hи Sпри приеме H', J, Kили N, но он также будет принимать Lи P(они включают слияние, но они не сливаются кончиком разработки ).
Чтобы также отклонить Lи P, вы можете изменить вопрос и спросить
Для всех предков push-коммитов (исключая текущий наконечник Develop и его предков):
- есть ли коммиты с двумя родителями?
- если нет, имеет ли хотя бы один такой коммит текущий совет развития своего (единственного) родителя?
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