Глиф Учебники

Урок 9. Работа в команде: pull request и rebase

Курс «Git» · урок 9 из 9 · 5 минут чтения

Когда над проектом работают несколько человек, главное правило простое: основная ветка main всегда рабочая, а каждая задача делается в своей ветке. Изменения попадают в main не напрямую, а через pull request — запрос на слияние, который коллеги просматривают перед тем, как принять.

Порядок работы над задачей

Обновите основную ветку и создайте от неё ветку задачи:

Bash
git switch main
git pull
git switch -c fix-login

Сделайте работу — столько коммитов, сколько нужно, — и отправьте ветку на сервер:

Bash
git push -u origin fix-login

Дальше — на сайте хостинга (GitHub, GitLab или другого сервиса, где лежит проект):

  1. Откройте pull request из fix-login в main. После отправки ветки сервис обычно сам подсказывает ссылку для этого — прямо в выводе git push или на странице проекта.
  2. Коллеги смотрят изменения и пишут замечания. Исправления — новыми коммитами в ту же ветку и git push: pull request обновится сам.
  3. Когда изменения одобрены, ветку сливают в main — обычно кнопкой на сайте.

После слияния обновите у себя main и удалите ветку задачи:

Bash
git switch main
git pull
git branch -d fix-login
ваш компьютер сайт хостинга 1 ветка задачи от свежей main 2 коммиты в fix-login git push замечания — новые коммиты 3 pull request fix-login → main коллеги смотрят изменения 4 слияние в main — когда одобрено git pull 5 обновить main удалить fix-login
Ветку fix-login отправляют на сайт через git push, pull request проверяют, исправления приходят новыми коммитами, после одобрения ветку сливают в main, а у себя main обновляют через git pull.

Хостинг может сливать 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:

Bash
git remote add upstream https://github.com/author/project.git
git fetch upstream
git merge upstream/main
Исходный проект author/project прав на запись нет Ваш форк ivan/project копия на хостинге форк — кнопкой pull request Ваш компьютер origin — ваш форк upstream — исходный проект git clone git push git fetch upstream
Форк — ваша копия чужого проекта на хостинге: его клонируют и отправляют в него коммиты как в origin, pull request идёт из форка в исходный проект, а свежие изменения забирают из upstream.

Ветка отстала от main: merge или rebase

Пока вы работали, в main появились чужие коммиты. Забрать их в свою ветку можно двумя способами.

Слиянием — как в уроке о ветках:

Bash
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.

1 2 main fix-login git merge main ничего не переписывает, в истории — коммит слияния 1′ 2′ 1 2 старые — не в ветке main fix-login git rebase main история — прямая линия, коммиты созданы заново — с новыми хешами
git merge main добавляет в fix-login коммит слияния и ничего не переписывает, а git rebase main создаёт коммиты ветки заново после свежей main, и история становится прямой линией.

Конфликт при rebase

Rebase переносит коммиты по одному, и конфликт может случиться на любом из них. Git остановится и подскажет:

Когда rebase нельзя

Не перебазируйте коммиты, которые уже есть у других: ветку main и общие ветки, где работают несколько человек. Rebase заменяет коммиты новыми, и у коллег история разойдётся с сервером — при следующем git pull их работа перемешается со старыми копиями ваших коммитов.

Свою ветку задачи, в которой работаете только вы, перебазировать можно, даже если она уже на сервере. Но обычный git push после этого откажется — история на сервере другая. Нужна принудительная отправка:

Bash
git push --force-with-lease

Принудительная отправка заменяет ветку на сервере вашей версией. --force-with-lease откажется, если ветка на сервере изменилась после вашего последнего fetch или pull, а --force перезапишет и чужие коммиты — чужая работа пропадёт. Никогда не отправляйте принудительно в main.

Если не уверены — используйте git merge main. Слияние всегда безопасно, rebase — инструмент для тех, кто понимает, что он переписывает.

Хорошие привычки

Коротко

Проверьте себя

1. Что такое pull request?
2. Как внести исправления по замечаниям к pull request?
3. Почему нельзя делать rebase ветки main, с которой работают другие?
4. Чем git push --force-with-lease безопаснее, чем git push --force?