- PVSM.RU - https://www.pvsm.ru -
В самом начале 2010 года Vincent Driessen [1] пишет отличную статью A successful Git branching model [2]. Для понимания того, о чем пойдет речь дальше, со статьей нужно, конечно же, познакомиться. А для тех, кому сложен язык оригинальной статьи, на хабре есть её отличный перевод [3].
С этого момента описанная модель ветвления GitFlow, начинает, что называется, расходиться по миру. Её берут на вооружение многие команды. Авторы пишут много статей об успешном её использовании. Она получает поддержку в большинстве инструментов, которые используют разработчики:
Кажется, что модель идеальна. Быть может так оно и есть, если у вас небольшая команда, неизменяемый скоуп релизов, высокая культура работы с VCS [14]. Тогда, действительно, GitFlow может и удовлетворит все ваши потребности. Но, к сожалению, описанные условия подходят не всем командам и не всем проектам. К слову, найти статьи, в которых бы авторы описывали проблемы этой модели не так уж и просто даже в 2016 году. Но как мы все знаем, серебряной пули нет [15], а, значит, и в этой модели всё хорошо далеко не для всех.
История начинается с того, что классический GitFlow предполагает большое число merge-коммитов. Причем проблема не в самих merge-коммитах (которые, как вы дальше увидите, всё равно будут присутствовать в истории), а в их огромном количестве. Дебаты на тему «Merge [16] vs Rebase [17]» часто встречаются на просторах интернета (поисковики подскажут). У Atlassian, кстати, есть хорошая статья [18], в которой описывается разница этих двух подходов. Так в чем же дело?
История коммитов становится просто ужасной. На фото ниже всего один день работы команды.
Да, у нас есть git log --first-parent
и другие возможности отфильтровать дерево, но это несильно помогает полноценному анализу истории. Если же у команды разработчиков, кроме классического GitFlow, нет никаких других соглашений по ведению Git-репозитория, то в этой истории можно будет целыми пачками наблюдать коммиты c абсолютно бессмысленными сообщениями "fix", "refactoring", "", и т.д. Это сделает историю коммитов практически непригодной даже для самого поверхностного анализа.
Если ваш релизный скоуп меняется (а в Agile [19] это бывает не редко), то классический GitFlow вам вряд ли подойдет. Если в вашем рабочем процессе часто встречаются фразы, попадающие под шаблон "Заказчику срочно нужна сборка, в которой [w]*", то с историей коммитов, наглядно представленной в предыдущем пункте, ваша жизнь превратится в сущий ад. Я не шучу.
git bisect
[20]Очень сложно объяснить, почему так важно, чтобы история коммитов была чистой. Опытным разработчикам не требуется объяснения, почему чистым должен быть исходный код, для них это утверждение — аксиома. На мой взгляд аналогия тут абсолютно прямая. Также как и каждая строчка чистого кода, каждый коммит истории должен быть на своем месте и понятен любому, даже стороннему, разработчику. Да, грязный код тоже может быть рабочим, но на сколько удобно с ним работать? Как быстро удастся в нем разобраться новому сотруднику? То же самое и с историей коммитов. Даже грязная история будет знать абсолютно всё обо всех изменениях в проекте, но удобно ли будет с ней работать?
Для того чтобы работа с Git-репозиторием была простой, удобной и понятной, на мой взгляд необходимы всего две вещи:
Линейность истории изменений. Это свойство ограничивает толщину дерева коммитов константой, делая его максимально простым и наглядным для анализа.
git cherry-pick
[21]. Или полностью отменены с помощью команды git revert
[22], которая в случае простого коммита гораздо проще, чем в случае merge-коммита.Если оба свойства выполняются, дерево коммитов будет выглядеть следующим образом:
Нужно совсем не много подредактировать классический GitFlow. При этом работа с develop, master, release и hotfix бранчами остаётся ровно такой же, как и в классическом GitFlow. Правки же коснутся исключительно работы с feature-бранчами.
Перед вливанием feature-бранча в итоговый, ему необходимо сделать интерактивный rebase [17] командой git rebase -i develop
, при этом все промежуточные коммиты в бранче слить (squash [23]'ить) в один. Бывают случаи, когда историю коммитов в feature-бранче имеет смысл оставить, но эти случаи на практике очень редки. При хорошей декомпозиции задач каждая небольшая задача представляет собой атомарное и логически завершенное изменение системы, которое отлично укладывается в одном коммите. Учитывая, что все изменения в рамках задачи можно соединить в один коммит в самый последний момент, во время работы над задачей разработчик может по-прежнему беспрепятственно создавать множество промежуточных коммитов, необходимых ему для потенциального отката. Ну и не лишним будет добавить, что есть отличная команда rerere [24], помогающая разработчикам, часто выполняющим операцию rebase.
Заливать feature-бранч в удалённый репозиторий необходимо с помощью команды git push --force
, так как в предыдущем пункте мы произвели rebase-бранча.
git merge --ff-only feature
, так как только в этом случае удастся сохранить линейность истории коммитов и избежать появления merge-коммита.Как видите, изменений по работе с репозиторием совсем не много. И, подводя некий итог этой части статьи, хочу поделиться ссылкой [25] на отличную статью, где также рассматриваются плюсы и минусы классического GitFlow и Rebase Flow.
Как я уже упоминал в самом начале статьи, поддержка классического GitFlow есть во множестве инструментов, в том числе и в различных менеджерах репозиториев. Поэтому дальше я рассмотрю вопрос о том, как сейчас обстоят дела с поддержкой Rebase Flow в популярных менеджерах репозиториев. При этом моя оценка будет в формате обычной университетской отметки.
Поддержка Rebase Flow: ХОРОШО
На самом деле, у GitHub есть практически всё что нужно. В настройках репозитория есть галочка «Allow squash merging».
Она позволяет при мерже pull request'а выбрать соответствующий пункт и отредактировать итоговое сообщение к коммиту
В результате pull request будет смержен линейно и все коммиты будут схлопнуты в один.
Единственный минус, который я вижу на стороне GitHub, это
Всё вышесказанное относится и к GitHub Enterprise [27], который может быть развернут на серверах вашей компании.
Поддержка Rebase Flow: НЕУДОВЛЕТВОРИТЕЛЬНО
А по факту её просто нет. Если вы хотите использовать в своей работе Rebase Flow, то BitBucket в этом вам никак не поможет, всё придётся делать самостоятельно.
И это удивительно, учитывая что по тексту этой статьи я не раз ссылался на отличные статьи с сайта Atlassian. Будем надеяться, что в будущем ситуация с поддержкой Rebase Flow изменится, тем более что задачи на это уже давно заведены
Давайте теперь посмотрим, что с поддержкой Rebase Flow у платного продукта от Atlassian.
Поддержка Rebase Flow: УДОВЛЕТВОРИТЕЛЬНО
Я рассматриваю BitBucket v4.5.2 и, возможно, в будущих версиях ситуация изменится в лучшую сторону. Сейчас же с поддержкой в BitBucket Server несколько лучше, чем в его облачном брате. Если у вас есть доступ к администраторам, то вы можете их любезно попросить в файле bitbucket.properties
поменять для вашего проекта/репозитория настройки мержа pull request'ов (документация [33])
plugin.bitbucket-git.pullrequest.merge.strategy.KEY.slug
— настройка для конкретного репозитория slug
в проекте KEY
.plugin.bitbucket-git.pullrequest.merge.strategy.KEY
— настройка для конкретного проекта KEY
.plugin.bitbucket-git.pullrequest.merge.strategy
— глобальное настройка для всего BitBucket Server.Значения настроек могут быть следующими
no-ff
— никакого fast-forward. Это значение по умолчанию.ff
–- при возможности, будет выполнен fast-forward мерж.ff-only
— всегда fast-forward мерж. Вы просто не сможете смержить pull request, если это нельзя сделать линейно.squash
— сливает все коммиты в один и не создает merge-коммита.squash-ff-only
— сливает все коммиты в один и не создает merge-коммита, но делает это только в том случае, если возможен fast-forward мерж.Как вы видите, настройки достаточно гибкие, но есть две проблемы
Как только эти две проблемы будут устранены, поддержку Rebase Flow у BitBucket можно будет оценить на отлично. А пока ...
Поддержка Rebase Flow: ХОРОШО
Оценивая поддержку на https://gitlab.com [35], мы, по сути, оцениваем поддержку в продукте GitLab EE [36], на базе которого он реализован. Что же касается поддержки Rebase Flow в GitLab CE [37], то её там попросту нет.
Для понимания того, как именно организована поддержка Rebase Flow, взглянем на настройки проекта
Как вы видите, тут даже есть промежуточный вариант полулинейной истории, когда merge-коммиты остаются, но возможность принять pull request появляется только в том случае, если feature-бранч является линейным продолжением. Если выбран этот вариант с полулинейной историей или «Fast-forward merge», у нас появляется дополнительная возможность управления pull request'ом. А именно появляется кнопка «Rebase onto ...», позволяющая сделать из feature-бранча линейное продолжение истории.
После чего можно без проблем принять pull request, который будет смержен без создания отдельного merge-коммита.
Более подробное описание этой функциональности можно посмотреть в документации (раз [38], два [39]). Несмотря на то, что скриншоты в ней немного устарели, она не потеряла своей актуальности. На этом в принципе поддержка Rebase Flow заканчивается. То что она вообще есть — это, конечно, плюс, но в ней явно не хватает
Сейчас большинство менеджеров Git-репозиториев реализуют поддержку Rebase Flow в каком-то виде. И удобство работы в них сейчас на порядок выше, чем несколько лет назад. Но всё-таки, на мой взгляд, минусы пока есть у всех продуктов, и я продолжаю верить, что в будущем они их исправят.
Автор: AT Consulting
Источник [40]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/120346
Ссылки в тексте:
[1] Vincent Driessen: http://nvie.com/about/
[2] A successful Git branching model: http://nvie.com/posts/a-successful-git-branching-model/
[3] перевод: https://habrahabr.ru/post/106912/
[4] Плагин: https://github.com/nvie/gitflow
[5] IDEA: https://plugins.jetbrains.com/plugin/7315
[6] Eclipse: http://eclipsesource.com/blogs/2015/06/22/git-flow-top-eclipse-mars-feature-3/
[7] SourceTree: https://www.sourcetreeapp.com/
[8] Git Extensions: https://gitextensions.github.io/
[9] Maven: https://bitbucket.org/atlassian/jgit-flow/wiki/Home
[10] Gradle: https://github.com/RobWin/jgitflow-gradle-plugin
[11] GitHub: https://github.com/
[12] BitBucket: https://bitbucket.org/
[13] GitLab: https://about.gitlab.com/
[14] VCS: https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D1%8F%D0%BC%D0%B8
[15] серебряной пули нет: https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D1%80%D0%B5%D0%B1%D1%80%D1%8F%D0%BD%D0%BE%D0%B9_%D0%BF%D1%83%D0%BB%D0%B8_%D0%BD%D0%B5%D1%82
[16] Merge: https://git-scm.com/docs/git-merge
[17] Rebase: https://git-scm.com/docs/git-rebase
[18] статья: https://www.atlassian.com/git/tutorials/merging-vs-rebasing
[19] Agile: https://ru.wikipedia.org/wiki/%D0%93%D0%B8%D0%B1%D0%BA%D0%B0%D1%8F_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%BE%D0%BB%D0%BE%D0%B3%D0%B8%D1%8F_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B8
[20] git bisect
: https://git-scm.com/docs/git-bisect
[21] git cherry-pick
: https://git-scm.com/docs/git-cherry-pick
[22] git revert
: https://git-scm.com/docs/git-revert
[23] squash: https://git-scm.com/book/ru/v1/%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B-Git-%D0%9F%D0%B5%D1%80%D0%B5%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C-%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8#Уплотнение-коммитов
[24] rerere: https://git-scm.com/docs/git-rerere
[25] ссылкой: https://www.atlassian.com/git/articles/git-team-workflows-merge-or-rebase/
[26] GitHub: https://github.com
[27] GitHub Enterprise: https://enterprise.github.com/home
[28] Forced non fast forward merge of pull request?: https://bitbucket.org/site/master/issues/6106/forced-non-fast-forward-merge-of-pull
[29] Provide the option to use "git merge --squash" for pull requests: https://bitbucket.org/site/master/issues/8995/provide-the-option-to-use-git-merge-squash
[30] Force fast-forward only merges on pull requests for specific branches: https://bitbucket.org/site/master/issues/9589/force-fast-forward-only-merges-on-pull
[31] Detect and handle rebasing and auto-merge in more situations: https://bitbucket.org/site/master/issues/6768/detect-and-handle-rebasing-and-auto-merge
[32] Atlassian BitBucket Server: https://ru.atlassian.com/software/bitbucket/download
[33] документация: https://confluence.atlassian.com/bitbucketserver/bitbucket-server-config-properties-776640155.html#BitbucketServerconfigproperties-Pullrequests
[34] GitLab: https://gitlab.com/
[35] https://gitlab.com: https://gitlab.com
[36] GitLab EE: https://about.gitlab.com/pricing/
[37] GitLab CE: https://about.gitlab.com/downloads/
[38] раз: http://doc.gitlab.com/ee/workflow/rebase_before_merge.html
[39] два: http://doc.gitlab.com/ee/workflow/ff_merge.html
[40] Источник: https://habrahabr.ru/post/283326/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.