Урок 9. Работа в команде: pull request и rebase
Когда над проектом работают несколько человек, главное правило простое: основная ветка main всегда рабочая, а каждая задача делается в своей ветке. Изменения попадают в main не напрямую, а через pull request — запрос на слияние, который коллеги просматривают перед тем, как принять.
Порядок работы над задачей
Обновите основную ветку и создайте от неё ветку задачи:
git switch main
git pull
git switch -c fix-loginСделайте работу — столько коммитов, сколько нужно, — и отправьте ветку на сервер:
git push -u origin fix-loginДальше — на сайте хостинга (GitHub, GitLab или другого сервиса, где лежит проект):
- Откройте pull request из
fix-loginвmain. После отправки ветки сервис обычно сам подсказывает ссылку для этого — прямо в выводеgit pushили на странице проекта. - Коллеги смотрят изменения и пишут замечания. Исправления — новыми коммитами в ту же ветку и
git push: pull request обновится сам. - Когда изменения одобрены, ветку сливают в
main— обычно кнопкой на сайте.
После слияния обновите у себя main и удалите ветку задачи:
git switch main
git pull
git branch -d fix-loginХостинг может сливать pull request по-разному: обычным слиянием, объединением всех коммитов в один (squash) или переносом коммитов (rebase). В двух последних случаях в main появляются новые коммиты, и git branch -d может ответить not fully merged. Если на сайте видно, что pull request слит, удалите ветку через git branch -D fix-login.
Pull request и merge request
Это одно и то же под разными именами: на GitHub — pull request, на GitLab — merge request. В нём видны все изменения ветки построчно, обсуждение и результаты автоматических проверок, если они настроены. Хороший запрос — небольшой и про одно дело. Опишите в нём, что изменено и зачем: проверяющему проще понять задачу из двух предложений, чем из двухсот строк кода.
Чужой проект: форк
Если прав на запись в репозиторий нет (например, это открытый проект, куда вы хотите прислать исправление), делают форк — свою копию репозитория на хостинге. Порядок такой: форк кнопкой на сайте → git clone своего форка → ветка → коммиты → git push в свой форк → pull request из форка в исходный проект.
Чтобы забирать свежие изменения исходного проекта, его добавляют вторым удалённым репозиторием, обычно под именем upstream:
git remote add upstream https://github.com/author/project.git
git fetch upstream
git merge upstream/mainВетка отстала от main: merge или rebase
Пока вы работали, в main появились чужие коммиты. Забрать их в свою ветку можно двумя способами.
Слиянием — как в уроке о ветках:
git switch main
git pull
git switch fix-login
git merge mainЭто безопасно и ничего не переписывает, но в истории появляется коммит слияния.
Перебазированием (rebase) — Git переносит ваши коммиты так, будто ветка начата от свежей main:
$ git switch fix-login
$ git rebase main
Successfully rebased and updated refs/heads/fix-login.История получается прямой линией, без коммитов слияния. Но коммиты при переносе создаются заново, с новыми хешами — в этом и сила, и опасность rebase.
Конфликт при rebase
Rebase переносит коммиты по одному, и конфликт может случиться на любом из них. Git остановится и подскажет:
- поправьте файлы, как в уроке Конфликты слияния, и выполните
git add файл; - продолжите:
git rebase --continue(если откроется редактор с сообщением — сохраните и закройте); - передумали —
git rebase --abort: ветка вернётся к состоянию до rebase.
Когда rebase нельзя
Не перебазируйте коммиты, которые уже есть у других: ветку main и общие ветки, где работают несколько человек. Rebase заменяет коммиты новыми, и у коллег история разойдётся с сервером — при следующем git pull их работа перемешается со старыми копиями ваших коммитов.
Свою ветку задачи, в которой работаете только вы, перебазировать можно, даже если она уже на сервере. Но обычный git push после этого откажется — история на сервере другая. Нужна принудительная отправка:
git push --force-with-leaseПринудительная отправка заменяет ветку на сервере вашей версией. --force-with-lease откажется, если ветка на сервере изменилась после вашего последнего fetch или pull, а --force перезапишет и чужие коммиты — чужая работа пропадёт. Никогда не отправляйте принудительно в main.
Если не уверены — используйте git merge main. Слияние всегда безопасно, rebase — инструмент для тех, кто понимает, что он переписывает.
Хорошие привычки
- Не коммитьте прямо в
mainобщего проекта — только через ветку и pull request. - Начинайте задачу со свежей
main:git switch mainиgit pull. - Делайте небольшие pull request: их быстрее проверяют, в них меньше конфликтов.
- Перед отправкой посмотрите
git diffиgit status— нет ли там лишних файлов и отладочного кода.
Коротко
- Каждая задача — своя ветка, в
mainизменения попадают через pull request (в GitLab — merge request). - Ветку отправляют
git push -u origin имя, исправления по замечаниям — новыми коммитами в неё же. - Форк — своя копия чужого проекта; исходный проект подключают как
upstream. - Отставшую ветку обновляют
git merge main(безопасно) илиgit rebase main(прямая история). - Rebase переписывает коммиты: только для своей ветки, после него —
git push --force-with-lease.