Скажем, у меня есть следующий локальный репозиторий с деревом фиксации как это:
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
мой, это - последний код стабильной версии, develop
мой, это - 'следующий' код выпуска, и feature
новая возможность, подготовленная к develop
.
То, что я хочу смочь сделать на моем удаленном repo использующие рычаги, для нажатий к feature
быть отказанным если фиксация f
прямой потомок develop
ГОЛОВА. т.е. дерево фиксации похоже на это, потому что функция была git rebase
на d
.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
Так это возможный к:
feature
?f
имеет потомок?Оттуда я проверил бы то, что ГЛАВА родительского ответвления, и посмотрите если f
предшественник соответствует родительскому главе филиала, чтобы определить, должна ли функция быть перебазирующейся.
Предполагая, что в удаленном репозитории есть копия ветки develop (ваше первоначальное описание описывает ее в локальном репозитории, но похоже, что она также существует в удаленном), вы сможете добиться то, что я думаю, вы хотите, но подход немного отличается от того, что вы предполагали.
История 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
метки присутствуют или нет.
Таким образом, вы могли бы задать вопросы вроде «является ли отправляемая фиксация потомком текущей ветки develop ?», Но вы не можете с уверенностью спросить, «какова родительская ветвь нажатой фиксации. ? ».
Наиболее надежный вопрос, который, кажется, приближается к тому, что вы хотите:
Для всех предков нажатой фиксации (за исключением текущей подсказки 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_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
, вы можете изменить вопрос и задать
Для всех предков нажатой фиксации (за исключением текущей подсказки develop ] и его предков):
- есть ли какие-либо коммиты с двумя родителями?
- если нет, имеет ли хотя бы одна такая фиксация текущая вершина 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
Помните, что, как описано в «Git: определение ветки, из которой произошла фиксация» , вы не можете легко определить ветвь, в которой была сделана эта фиксация (ветки могут быть переименован, перемещен, удален ...), хотя git branch --contains
- это начало.
git branch --contains
не перечислит ветвь функции и не перечислит ветвь develop
,
/ refs / Heads / develop
. Если два коммита совпадают по идентификатору, все готово (это будет означать, что ветвь feature
берет свое начало в ГОЛОВА развить
).
У меня есть решение вашей общей проблемы (определите, является ли функция
наследником develop
), но оно не работает, используя описанный вами метод.
Вы можете использовать git branch --contains
, чтобы перечислить все ветки, произошедшие от кончика develop
, затем используйте grep
, чтобы убедиться, что функция
входит в их число.
git branch --contains develop | grep "^ *feature$"
Если он среди них, он напечатает «характеристика»
на стандартный вывод и получит код возврата 0. В противном случае он ничего не напечатает и получит код возврата 1.