gitworkflows
Имя
gitworkflows - Обзор рекомендуемых рабочих процессов с Git
Синопсис
git *
Описание
В данном документе мы пытаемся описать и мотивировать некоторые элементы рабочего процесса, используемые для git.git. Многие идеи применимы в общем случае, хотя полный рабочий процесс редко требуется для небольших проектов с меньшим количеством участников.
Мы формулируем набор rules для быстрого справочника, в то время как текст пытается мотивировать каждый из них. Не следует воспринимать их буквально; следует ценить разумные причины ваших действий выше, чем руководства, подобные этому.
Разделение изменений
Как общее правило, вы должны стараться разбивать свои изменения на небольшие логические шаги и коммитить каждый из них. Они должны быть согласованными, работать независимо от последующих коммитов, проходить набор тестов и т.д. Это значительно упрощает процесс проверки и делает историю более полезной для последующего анализа и проверки, например, с помощью git-blame[1] и git-bisect[1].
Чтобы достичь этого, постарайтесь разбить свою работу на небольшие шаги с самого начала. Всегда легче объединить несколько коммитов, чем разделить один большой коммит на несколько. Не бойтесь делать слишком маленькие или несовершенные шаги по пути. Вы всегда можете вернуться позже и отредактировать коммиты с помощью git rebase --interactive перед их публикацией. Вы можете использовать git stash push --keep-index для запуска набора тестов независимо от других несохраненных изменений; см. раздел ПРИМЕРЫ в git-stash[1].
Управление ветками
Существуют два основных инструмента, которые можно использовать для включения изменений из одной ветки в другую: git-merge[1] и git-cherry-pick[1].
Слияния имеют много преимуществ, поэтому мы стараемся решать как можно больше проблем с помощью одних только слияний. Выбор отдельных коммитов всё же иногда полезен; см. «Слияние вверх» ниже для примера.
Самое главное, слияние работает на уровне ветвей, а выбор отдельных коммитов — на уровне коммита. Это означает, что слияние может перенести изменения из 1, 10 или 1000 коммитов с одинаковой лёгкостью, что, в свою очередь, означает, что рабочий процесс масштабируется намного лучше для большого числа участников (и вкладов). Слияния также легче понять, потому что коммит слияния является «обещанием», что все изменения из всех его родителей теперь включены.
Конечно, есть компромисс: слияния требуют более тщательного управления ветками. В следующих подразделах обсуждаются важные моменты.
Выпуск
По мере того, как определённая функция переходит от экспериментальной к стабильной, она также «выпускается» между соответствующими ветками программного обеспечения. git.git использует следующие integration branches:
-
maintотслеживает коммиты, которые должны войти в следующий «релиз обслуживания», т. е. обновление последней выпущенной стабильной версии; -
masterотслеживает коммиты, которые должны войти в следующий релиз; -
nextпредназначен как ветка тестирования для тем, которые тестируются на стабильность для master.
Существует четвёртая официальная ветка, которая используется несколько иначе:
-
seen(патчи, просмотренные разработчиком) — это ветка интеграции для вещей, которые ещё не совсем готовы к включению (см. «Ветки интеграции» ниже).
Каждая из четырёх веток обычно является прямым потомком ветки, расположенной над ней.
По сути, функция входит в нестабильную ветку (обычно next или seen), и «выпускается» в master для следующего релиза, как только она считается достаточно стабильной.
Слияние вверх
«Спуск» (выпуск в предыдущие ветки), обсуждаемый выше, не может быть выполнен путём фактического слияния вниз, поскольку это слило бы all изменения в нестабильной ветке в стабильную. Отсюда и следующее:
Всегда фиксируйте свои изменения в самой старой поддерживаемой ветке, которая их требует. Затем (периодически) сливайте ветки интеграции вверх друг в друга.
Это обеспечивает очень контролируемый поток исправлений. Если вы заметите, что применили исправление, например, к master, которое также требуется в maint, вам нужно будет выбрать отдельные коммиты (используя git-cherry-pick[1]) вниз. Это произойдёт несколько раз и не должно вызывать беспокойства, если вы не делаете это слишком часто.
Ветки тем
Любая непростая функция потребует нескольких патчей для реализации и может получить дополнительные исправления ошибок или улучшения в течение своего жизненного цикла.
Фиксирование всего непосредственно в ветках интеграции приводит к множеству проблем: Плохие коммиты нельзя отменить, поэтому их необходимо отменять по одному, что создаёт запутанную историю и ещё больше увеличивает вероятность ошибок, когда вы забываете отменить часть группы изменений. Параллельная работа смешивает изменения, что создаёт ещё большую путаницу.
Использование «веточек тем» решает эти проблемы. Название достаточно самопонятно, с оговоркой, которая вытекает из правила «слияния вверх» выше:
Создавайте отдельную ветку для каждой темы (функции, исправления ошибок и т. д.). Отделяйте её от старейшей ветки интеграции, в которую вы, в конечном счёте, хотите её слить.
Тогда многие вещи можно сделать очень естественно:
-
Чтобы включить функцию/исправление ошибки в ветку интеграции, просто слийте её. Если тема развивалась дальше тем временем, сливайте снова. (Обратите внимание, что вам необязательно сначала сливать её в самую старую ветку интеграции. Например, вы можете сначала слить исправление ошибки в
next, дать ему время на тестирование и слить вmaint, когда вы будете уверены в его стабильности.) -
Если вы обнаружите, что вам нужны новые функции из ветки
otherдля продолжения работы над своей темой, слийтеotherвtopic. (Однако не делайте этого «просто по привычке», см. ниже.) -
Если вы обнаружите, что создали ветку с ошибкой и хотите переместить её «назад во времени», используйте git-rebase[1].
Обратите внимание, что последний пункт противоречит двум другим: тему, которая была слита в другое место, не следует перебазировать. См. раздел ВОССТАНОВЛЕНИЕ ПОСЛЕ ПЕРЕБАЗИРОВАНИЯ ВЕРСИЙ В git-rebase[1].
Мы должны отметить, что «по привычке» (регулярно без реальной причины) сливать ветку интеграции в ваши темы — и, как следствие, сливать что-либо upstream в downstream регулярно — не приветствуется:
Не сливайте в downstream, кроме как с хорошей причиной: изменения API upstream влияют на вашу ветку; ваша ветка больше не сливается с upstream чисто; и т. д.
В противном случае тема, которая была слита, вдруг содержит больше одного (хорошо отделённого) изменения. Многочисленные полученные небольшие слияния сильно загромоздят историю. Любой, кто позже изучит историю файла, должен будет выяснить, повлияло ли это слияние на тему, находящуюся в разработке. Upstream даже может непреднамеренно слиться в «более стабильную» ветку. И так далее.
Жертвенная интеграция
Если вы следовали последнему абзацу, у вас теперь будет много небольших веток тем, и вы иногда будете задаваться вопросом, как они взаимодействуют. Возможно, результат их слияния даже не работает? Но, с другой стороны, мы хотим избегать слияния их в «стабильные» ветки, потому что такие слияния трудно отменить.
Конечно, решение состоит в том, чтобы сделать слияние, которое мы можем отменить: слить в жертвовательную ветку.
Для тестирования взаимодействия нескольких тем сливайте их в ветку, которую можно удалить. Вы никогда не должны опираться на такую ветку!
Если вы очень чётко укажете, что эта ветка будет удалена сразу после тестирования, вы даже можете опубликовать её, например, чтобы дать тестировщикам возможность работать с ней или другим разработчикам возможность увидеть, будут ли их текущие работы совместимы. git.git имеет такую официальную ветку жертвенной интеграции под названием seen.
Управление ветками для релиза
Предполагая, что вы используете подход слияния, обсуждаемый выше, при выпуске вашего проекта вам потребуется выполнить дополнительные операции по управлению ветками.
Релиз функции создаётся из ветки master, поскольку master отслеживает коммиты, которые должны войти в следующий релиз функции.
Ветка master должна быть супермножеством maint. Если это условие не выполняется, то maint содержит некоторые коммиты, которые не включены в master. Поэтому исправления, представленные этими коммитами, не будут включены в ваш релиз функции.
Чтобы убедиться, что master является супермножеством maint, используйте git log:
git log master..maint
Эта команда не должна выводить какие-либо коммиты. В противном случае переключитесь на master и слийте maint в неё.
Теперь вы можете продолжить создание релиза функции. Примените тег к концу master, указывающий версию релиза:
git tag -s -m "Git X.Y.Z" vX.Y.Z master
Вам необходимо передать новый тег на публичный сервер Git (см. «РАСПРЕДЕЛЁННЫЕ РАБОЧИЕ ПРОЦЕССЫ» ниже). Это делает тег доступным для других, отслеживающих ваш проект. Передача может также запустить обработчик после обновления для выполнения задач, связанных с выпуском, таких как создание скомпилированных архивов релиза и страниц документации в предварительно отформатированном виде.
Аналогично, для релиза обслуживания maint отслеживает коммиты, подлежащие выпуску. Поэтому в шагах выше просто поставьте тег и передайте maint, а не master.
Управление ветками обслуживания после релиза функции
После релиза функции вам необходимо управлять ветками обслуживания.
Во-первых, если вы хотите продолжать выпускать исправления обслуживания для релиза функции, созданного перед последним, то вам необходимо создать другую ветку для отслеживания коммитов для этого предыдущего релиза.
Для этого текущая ветка обслуживания копируется в другую ветку с номером предыдущей версии релиза (например, maint-X.Y.(Z-1), где X.Y.Z — текущий релиз).
git branch maint-X.Y.(Z-1) maint
Ветка maint должна быть теперь быстро перенаправлена на недавно выпущенный код, чтобы можно было отслеживать исправления обслуживания для текущего релиза:
-
git checkout maint -
git merge --ff-only master
Если слияние не удаётся, потому что это не быстрое перенаправление, то возможно, некоторые исправления в maint были пропущены в релизе функции. Этого не произойдёт, если содержимое веток было проверено, как описано в предыдущем разделе.
Управление ветками для «следующей» и «просмотренной» после релиза функции
После выпуска функции интегрированная ветка next может быть необязательно перемотана и перестроена с вершины master с использованием оставшихся тем в next:
-
git switch -C next master -
git merge ai/topic_in_next1 -
git merge ai/topic_in_next2 -
…
Преимущества этого подхода заключаются в том, что история next будет чистой. Например, некоторые темы, слиянные в next , могли первоначально выглядеть многообещающими, но позже оказались нежелательными или преждевременными. В таком случае тема отменяется из next , но в истории остаётся факт её первоначального слияния и отмены. Пересоздавая next, вы даёте таким темам новую возможность, и релиз функции является подходящим моментом для этого.
Если вы это сделаете, необходимо опубликовать объявление о том, что next была перемотана и перестроена.
То же самое перемотка и перестройка могут быть применены к seen. Общественное объявление не обязательно, так как seen является временной веткой, как описано выше.
Распределённые рабочие процессы
После предыдущего раздела вы должны понимать, как управлять темами. Как правило, вы не единственный человек, работающий над проектом, поэтому вам придётся делиться своей работой.
Грубо говоря, существуют два важных рабочих процесса: слияние и патчи. Важное различие состоит в том, что процесс слияния может распространять всю историю, включая слияния, в то время как патчи не могут. Оба рабочих процесса могут использоваться параллельно: в git.git, только системные администраторы используют процесс слияния, в то время как все остальные отправляют патчи.
Обратите внимание, что администраторы могут ввести ограничения, например, требования «Подписано», которым должны соответствовать все отправленные коммиты/патчи. Для получения дополнительной информации обратитесь к документации вашего проекта.
Процесс слияния
Процесс слияния работает путём копирования ветвей между «upstream» и «downstream». «Upstream» может слить вносимые изменения в официальную историю, «downstream» базируется на официальной истории.
Существует три основных инструмента, которые могут быть использованы для этого:
-
git-push[1] копирует ваши ветки в удалённый репозиторий, обычно в тот, к которому могут обращаться все участники;
-
git-fetch[1] копирует удалённые ветки в ваш репозиторий; и
-
git-pull[1] выполняет fetch и merge одновременно.
Обратите внимание на последний пункт. Не используйте not git pull, если вы не хотите фактически сливать удалённую ветку.
Получение изменений просто:
git push <remote> <branch> и сообщите всем, где они могут делать fetch.
Вам всё ещё нужно сообщать людям другими способами, например, по почте. (Git предоставляет git-request-pull[1] для отправки предварительно отформатированных запросов на слияние администраторам upstream, чтобы упростить эту задачу.)
Если вы просто хотите получить самые последние копии интегрированных ветвей, оставаться в курсе тоже легко:
Используйте git fetch <remote> или git remote update для синхронизации.
Затем просто разветвляйте свои темы от стабильных удалённых репозиториев, как описано ранее.
Если вы администратор и хотите слить темы других людей в интегрированные ветки, они, как правило, отправят запрос по почте. Такой запрос выглядит так
Please pull from
<URL> <branch> В этом случае git pull может выполнить fetch и merge одновременно следующим образом.
git pull <URL> <branch>
Иногда администратор может столкнуться с конфликтами при попытке получить изменения из «downstream». В этом случае он может попросить «downstream» выполнить слияние и разрешить конфликты самостоятельно (возможно, они лучше знают, как их разрешить). Это один из редких случаев, когда «downstream» should выполняет слияние из «upstream».
Процесс с использованием патчей
Если вы участник, отправляющий изменения в upstream в виде электронных писем, вам следует использовать темы, как обычно (см. выше). Затем используйте git-format-patch[1] для создания соответствующих электронных писем (настоятельно рекомендуется вместо ручного форматирования, так как это облегчает работу администратору).
-
git format-patch -M upstream..topicдля преобразования в предварительно отформатированные файлы патчей -
git send-email --to=<recipient> <patches>
См. руководства пользователя git-format-patch[1] и git-send-email[1] для получения дополнительных сведений об использовании.
Если администратор сообщит вам, что ваш патч больше не применим к текущему upstream, вам необходимо перебазировать вашу тему (вы не можете использовать слияние, так как не можете форматировать слияния):
git pull --rebase <URL> <branch>
Затем вы можете исправить конфликты во время перебазирования. Предположительно, вы не опубликовали свою тему иначе, как по электронной почте, поэтому перебазирование не является проблемой.
Если вы получаете подобный ряд патчей (как администратор или, возможно, как читатель списка рассылки, в который он был отправлен), сохраните письма в файлы, создайте новую тему ветки и используйте git am для импорта коммитов:
git am < patch
Стоит отметить возможность трёхстороннего слияния, которая может помочь при возникновении конфликтов: git am -3 будет использовать информацию из индекса, содержащуюся в патчах, для определения базового слияния. Смотрите git-am[1] для других вариантов.
См. также
gittutorial[7], git-push[1], git-pull[1], git-merge[1], git-rebase[1], git-format-patch[1], git-send-email[1], git-am[1]
gitworkflows
© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/gitworkflows