Как найти ближайшего родителя ответвления Мерзавца?

Скажем, у меня есть следующий локальный репозиторий с деревом фиксации как это:

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 предшественник соответствует родительскому главе филиала, чтобы определить, должна ли функция быть перебазирующейся.

386
задан Scott 22 July 2019 в 04:12
поделиться

3 ответа

Предполагая, что в удаленном репозитории есть копия ветки 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
330
ответ дан 22 November 2019 в 23:51
поделиться

Помните, что, как описано в «Git: определение ветки, из которой произошла фиксация» , вы не можете легко определить ветвь, в которой была сделана эта фиксация (ветки могут быть переименован, перемещен, удален ...), хотя git branch --contains - это начало.

  • Вы можете вернуться от фиксации к фиксации, пока git branch --contains не перечислит ветвь функции и не перечислит ветвь develop ,
  • сравните этот коммит SHA1 с / refs / Heads / develop

. Если два коммита совпадают по идентификатору, все готово (это будет означать, что ветвь feature берет свое начало в ГОЛОВА развить ).

8
ответ дан 22 November 2019 в 23:51
поделиться

У меня есть решение вашей общей проблемы (определите, является ли функция наследником develop ), но оно не работает, используя описанный вами метод.

Вы можете использовать git branch --contains , чтобы перечислить все ветки, произошедшие от кончика develop , затем используйте grep , чтобы убедиться, что функция входит в их число.

git branch --contains develop | grep "^ *feature$"

Если он среди них, он напечатает «характеристика» на стандартный вывод и получит код возврата 0. В противном случае он ничего не напечатает и получит код возврата 1.

52
ответ дан 22 November 2019 в 23:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: