Comments 14
Строго говоря, тесты прошедшие для первого мерж-реквеста тоже не совсем актуальны, только если это не fast-forward merge. После мержа код может измениться и тесты провалятся.
Вот у нас открыт мерж-реквест. Ветка мастер — зелёная (тесты проходят). Ветка фичи тоже зелёная. Можно мержить, ага?
git log --graph --decorate --oneline --all
# строки "fail|pass" не от git log,
# я их сам дописал
* ec72de2 (feature) C – pass
| * 169ab86 (HEAD -> master) B – pass
|/
* 61d0f69 A
В результате получается новый мерж-коммит с новым, ранее не протестированным кодом. Он может зафейлиться.
* fd4d2ad (HEAD -> master) M – fail
|\
| * ec72de2 (feature) C – pass
* | 169ab86 B – test pass
|/
* 61d0f69 A
Что с этим делать? Можно требовать, чтобы каждый мерж был линейным или псевдо-линейным.
Можно заребейзить ветку
feature
наmaster
:
git checkout feature; git rebase master * 9346bff (HEAD -> feature) C – test pass * 169ab86 (master) B – test pass * 61d0f69 A
Если после ребейза тесты проходят, то ветку можно мержить:
Либо позволяем случиться fast-forward merge:
git checkout master git merge feature * 9346bff (HEAD -> master, feature) C * 169ab86 B * 61d0f69 A
Либо не позволяем, чтобы сохранить хоть какую-то информацию о ходе разработки в истории git. Это особенно полезно, когда в ветке более одного коммита. :
git checkout master git merge feature --no-ff
Мерж-коммит здесь "пустой", в нём то же содержимое, что и в
C
.
Поэтому тесты на нём гарантированно пройдут.
* b4d0b85 (HEAD -> master) M - pass |\ | * 9346bff (feature) C |/ * 169ab86 B * 61d0f69 A
Иногда ребейзить бывает очень сложно — коммитов в ветке много, конфликт случился где-то в самом начале и его приходится разрешать много раз. В таком случае можно сделать обратный мерж:
git checkout feature git merge master * 4122e75 (HEAD -> feature) M — pass |\ | * 169ab86 (master) B * | ec72de2 C |/ * 61d0f69 A
В процессе мержа нужно разрешить конфликты.
Если результат мержа проходит тесты, то можно принимать мерж-реквест:
* 4122e75 (HEAD -> master, feature) M – pass |\ | * 169ab86 B * | ec72de2 C |/ * 61d0f69 A
Если результат мержа не проходит тесты, то я бы рекомендовал откатить
feature
на один коммит назад, чтобы потом не мержить вmaster
несколько мерж-коммитов. Они будут лишний раз запутывать историю.
Ещё одна причина не ребейзить — в каждой команде свои правила работы с git. Где-то рейбейзить не принято или вообще запрещено, и на то есть веские причины. Обратный мерж позволит протестировать изменения, не подвергая риску ветку master
.
Интересно, не встречал такую фичу. Всё, что смог найти — запрет на принятие мерж-реквеста, когда fast-forward мерж невозможен.
Не могли бы вы сделать скриншот конвейера, выполненного на таком авто-мерже?
Хм, а эта фича точно есть в Gitlab?
Нашел только запрос на ее реализацию — https://gitlab.com/gitlab-org/gitlab-ce/issues/4176
На каждый мерж-реквест создается новая ссылка в refs/merge-requests/
– это такие же ветки, только в другой директории. Они удобны для интеграции с CI-сервером и позволяют зачекаутить ветку, даже когда мерж-реквест открыт из форка репозитория. Но автоматических мержей "под капотом" там вроде бы нет.
Ха! Ну да, это я сам год назад задался этим вопросом и потом нашёл и опубликовал ответ. Нет, там находится предложенная на мерж ветка.
Автомерж вообще не всегда возможен, потому что в общем случае будут конфликты.
Можно сделать отдельный этап в конвейере (описать его в .gitlab-ci.yml
), который будет мержить ветки и прогонять на них все тесты. Но тут возможны неравнозначные исходы:
- Мерж был без конфликтов, но не прошла сборка или тесты. Это достоверно негативный результат.
- Автоматический мерж не получился, так как были конфликты. Конвейер завершился с неуспехом, но этом нам не даёт никакой информации: если замержить вручную, то тесты могут и пройти.
Если требовать псевдолинейную историю, то конфликтов гарантированно не будет, поэтому результат автомержа будет достоверным. Чтобы не реализовывать его руками, предлагаю голосовать за вышеуказанную фичу. Когда-нибудь реализуют.
Вроде бы можно приспособить триггеры. Попробую на выходных собрать proof-of-concept с таким обновлением. Если получится — выложу.
1) Есть первый мерж-реквест в мастер, по нему был запущен конвейер, тесты успешно прошли.
2) Делаем второй мерж-реквест в мастер, по нему тоже запускается конвейер, и тесты тоже успешно проходят.
3) Теперь принимаем первый мерж-реквест.
4) Итог — у нас есть изменившийся мастер и «старый» второй мерж-реквест. Тесты, ранее успешно прошедшие для второго мерж-реквеста, теперь не актуальны. Теперь, возможно, тесты во втором мерж-реквесте упадут — мастер-то изменился.
Для данного сценария ручное решение (для Community Edition):
- После вашего шага 3 нужно либо сделать
git merge master
, либоgit rebase master
(предпочтительней), находясь во второй фича-ветке - После обновления фича-ветки новый пуш в Gitlab, далее ждем прогона тестов (т.к. в Gitlab есть кнопка
Merge When Build Succeds
, то можно и не ждать особо)
Либо вариант для платной версии Enterprise Edition, все шаги выше, но через интерфейс Gitlab'а — https://docs.gitlab.com/ee/workflow/rebase_before_merge.html
Вышел GitLab 9.1: Service Desk, Burndown Charts и канареечные развертывания