Pull to refresh

Comments 14

UFO just landed and posted this here

Строго говоря, тесты прошедшие для первого мерж-реквеста тоже не совсем актуальны, только если это не 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

Что с этим делать? Можно требовать, чтобы каждый мерж был линейным или псевдо-линейным.


  1. Можно заребейзить ветку feature на master:


    git checkout feature;
    git rebase master
    
    * 9346bff (HEAD -> feature) C – test pass
    * 169ab86 (master) B – test pass
    * 61d0f69 A

    Если после ребейза тесты проходят, то ветку можно мержить:


    1. Либо позволяем случиться fast-forward merge:


      git checkout master
      git merge feature
      
      * 9346bff (HEAD -> master, feature) C
      * 169ab86 B
      * 61d0f69 A

    2. Либо не позволяем, чтобы сохранить хоть какую-то информацию о ходе разработки в истории git. Это особенно полезно, когда в ветке более одного коммита. :


      git checkout master
      git merge feature --no-ff

      Мерж-коммит здесь "пустой", в нём то же содержимое, что и в C.
      Поэтому тесты на нём гарантированно пройдут.


      *   b4d0b85 (HEAD -> master) M - pass
      |\
      | * 9346bff (feature) C
      |/
      * 169ab86 B
      * 61d0f69 A


  2. Иногда ребейзить бывает очень сложно — коммитов в ветке много, конфликт случился где-то в самом начале и его приходится разрешать много раз. В таком случае можно сделать обратный мерж:


    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.

UFO just landed and posted this here
UFO just landed and posted this here

На каждый мерж-реквест создается новая ссылка в refs/merge-requests/ – это такие же ветки, только в другой директории. Они удобны для интеграции с CI-сервером и позволяют зачекаутить ветку, даже когда мерж-реквест открыт из форка репозитория. Но автоматических мержей "под капотом" там вроде бы нет.

UFO just landed and posted this here

Ха! Ну да, это я сам год назад задался этим вопросом и потом нашёл и опубликовал ответ. Нет, там находится предложенная на мерж ветка.


Автомерж вообще не всегда возможен, потому что в общем случае будут конфликты.


Можно сделать отдельный этап в конвейере (описать его в .gitlab-ci.yml), который будет мержить ветки и прогонять на них все тесты. Но тут возможны неравнозначные исходы:


  1. Мерж был без конфликтов, но не прошла сборка или тесты. Это достоверно негативный результат.
  2. Автоматический мерж не получился, так как были конфликты. Конвейер завершился с неуспехом, но этом нам не даёт никакой информации: если замержить вручную, то тесты могут и пройти.

Если требовать псевдолинейную историю, то конфликтов гарантированно не будет, поэтому результат автомержа будет достоверным. Чтобы не реализовывать его руками, предлагаю голосовать за вышеуказанную фичу. Когда-нибудь реализуют.

UFO just landed and posted this here

Вроде бы можно приспособить триггеры. Попробую на выходных собрать proof-of-concept с таким обновлением. Если получится — выложу.

1) Есть первый мерж-реквест в мастер, по нему был запущен конвейер, тесты успешно прошли.
2) Делаем второй мерж-реквест в мастер, по нему тоже запускается конвейер, и тесты тоже успешно проходят.
3) Теперь принимаем первый мерж-реквест.
4) Итог — у нас есть изменившийся мастер и «старый» второй мерж-реквест. Тесты, ранее успешно прошедшие для второго мерж-реквеста, теперь не актуальны. Теперь, возможно, тесты во втором мерж-реквесте упадут — мастер-то изменился.

Для данного сценария ручное решение (для Community Edition):


  1. После вашего шага 3 нужно либо сделать git merge master, либо git rebase master (предпочтительней), находясь во второй фича-ветке
  2. После обновления фича-ветки новый пуш в Gitlab, далее ждем прогона тестов (т.к. в Gitlab есть кнопка Merge When Build Succeds, то можно и не ждать особо)

Либо вариант для платной версии Enterprise Edition, все шаги выше, но через интерфейс Gitlab'а — https://docs.gitlab.com/ee/workflow/rebase_before_merge.html

UFO just landed and posted this here
Sign up to leave a comment.