$ sudo teach IT
Модуль 6 · Работа в команде · Урок 6.1

Pull request

Вы отправите ветку на GitHub, откроете свой первый pull request и сольёте его в main.

Теория + практика~20 минутНовичокpull requestGitHub flow

Зачем нужен pull request

Pull request (сокращённо PR, по-русски «запрос на слияние») — это предложение на GitHub влить изменения из одной ветки в другую, например из feature/contacts в main. К предложению прикладывают описание, его можно обсудить и поправить, и только потом нажать кнопку слияния. В уроке вы пройдёте весь путь на проекте «Визитка»: отправите ветку, откроете PR, сольёте его и приведёте компьютер в порядок.

Раньше вы вливали ветки командой git merge у себя на компьютере, а в main на GitHub отправляли всё подряд. Одному это удобно. В команде нет: чужие правки не должны попадать в рабочую ветку, пока их никто не посмотрел. Поэтому main принято не трогать напрямую, а менять только через pull request.

Простыми словами

Представьте общую тетрадь с конспектами. Прежде чем вклеить в неё новую страницу, вы показываете её соседу: «Посмотри, всё ли понятно?». Сосед читает, пишет на полях замечания, вы поправляете, и только потом страница попадает в тетрадь. Pull request — это такая «страница на проверке».

Официальный термин

Название можно перевести как «прошу забрать (pull) мои изменения». Вы просите владельца ветки main сделать pull из вашей ветки. Две ветки в PR называют так: base — куда вливаем (у нас main), compare — что вливаем (у нас feature/contacts).

Частая путаница: pull request и git pull

Это разные вещи. git pull — команда Git: забрать чужие изменения на ваш компьютер. Pull request — функция GitHub: предложение влить ветку. Команды git pull-request не существует: Git про PR ничего не знает, их придумал GitHub.

Весь путь одной схемой

Рабочий цикл, который GitHub называет GitHub flow, выглядит так:

Схема
main:      A---B---C-----------------M---
                \               /
feature/contacts D---E---------

1. ветка        2. коммиты      3. push
4. pull request 5. обсуждение   6. слияние (M) и удаление ветки

На схеме: от коммита C в main отходит ветка с двумя коммитами D и E. После проверки они вливаются в main коммитом слияния M. Шаги 1–3 вы уже умеете, шаги 4–6 — тема урока.

Ветка и push

Начинаем, как всегда, с ветки. Задача — добавить на страницу раздел «Контакты». Убедитесь, что вы на main и всё актуально, затем создайте ветку и внесите правку.

Терминал
$ git switch main
$ git pull
Already up to date.
$ git switch -c feature/contacts
Switched to a new branch 'feature/contacts'

Откройте index.html в VS Code и вставьте перед строкой с <footer> новый раздел:

HTML · index.html
  <section id="contacts">
    <h2>Контакты</h2>
    <p>Почта: <a href="mailto:alex@example.com">alex@example.com</a></p>
  </section>

Подставьте свою почту. Теперь посмотрите разницу, закоммитьте и отправьте ветку на GitHub:

Терминал
$ git diff
@@ -20,6 +20,10 @@
     </ul>
     <p><a href="projects.html">Все проекты</a></p>
   </section>
+  <section id="contacts">
+    <h2>Контакты</h2>
+    <p>Почта: <a href="mailto:alex@example.com">alex@example.com</a></p>
+  </section>
   <footer><p>&copy; 2026 Алекс Иванов. Сайт опубликован на GitHub Pages.</p></footer>
 </body>
 </html>
$ git add index.html
$ git commit -m "Добавить раздел «Контакты»"
[feature/contacts 389da8c] Добавить раздел «Контакты»
 1 file changed, 4 insertions(+)
$ git push -u origin feature/contacts
...
remote: Create a pull request for 'feature/contacts' on GitHub by visiting:
remote:      https://github.com/alex-ivanov/portfolio/pull/new/feature/contacts
remote:
To https://github.com/alex-ivanov/portfolio.git
 * [new branch]      feature/contacts -> feature/contacts
branch 'feature/contacts' set up to track 'origin/feature/contacts'.

Разбор по строкам

  • git diff — строки с плюсом добавлены; контекст вокруг показывает, что раздел встал между «Мои проекты» и подвалом (хвост вывода сокращён).
  • [feature/contacts 389da8c] — коммит сделан в ветке feature/contacts, его хеш начинается с 389da8c. У вас хеш будет другой.
  • git push -u origin feature/contacts — отправить ветку на GitHub под тем же именем; -u запомнит связь с origin/feature/contacts, и дальше хватит просто git push.
  • Строки с remote: пишет сам GitHub, а не Git: он подсказывает адрес, по которому можно открыть pull request. Это первая подсказка, что делать дальше.
  • * [new branch] — на GitHub появилась новая ветка; branch ... set up to track — локальная ветка связана с удалённой.

Открываем pull request

Откройте репозиторий github.com/alex-ivanov/portfolio (со своим логином). Сразу после push над списком файлов появится жёлтый баннер с кнопкой Compare & pull request (в переводе «сравнить и создать pull request»). Нажмите её.

Если баннер уже пропал, откройте вкладку Pull requests и нажмите New pull request: там два выпадающих списка, в которых нужно выбрать ветки самостоятельно. Что на странице нового PR:

  • выпадающий список base — ветка, в которую вливаем: оставьте main;
  • выпадающий список compare — ваша ветка: feature/contacts;
  • поле с заголовком — коротко, как сообщение коммита: «Добавить раздел «Контакты»»;
  • поле с описанием — что сделано, зачем и как проверить;
  • кнопка создания — Create pull request (надпись в интерфейсе может немного отличаться регистром букв).

Образец описания, который можно взять за основу:

Markdown · описание pull request
Что сделано: добавил в index.html раздел «Контакты» с почтой.
Зачем: на сайте не было способа связаться со мной.
Как проверить: открыть index.html в браузере, раздел виден перед подвалом.

Нажмите Create pull request. Откроется страница вашего PR. У первого PR в репозитории номер #1: у pull request и у issue (задач, о них — через урок) общая нумерация. Вверху четыре вкладки:

ВкладкаЧто показывает
ConversationОписание, комментарии, ревью и события: «слили», «закрыли»
CommitsСписок коммитов ветки. У вас пока один — «Добавить раздел «Контакты»»
ChecksРезультаты автоматических проверок и сборок (пока пусто)
Files changedРазница в файлах, как git diff: зелёные строки добавлены, красные удалены

PR живёт, пока вы пушите в ветку

Pull request привязан к ветке, а не к коммиту. Если после открытия PR вы закоммитите в feature/contacts ещё раз и сделаете git push, новый коммит появится в том же PR сам. Отдельный PR создавать не нужно.

Слияние pull request

Ревью (когда кто-то читает ваш код) разберём в следующем уроке, а пока перейдите на вкладку Conversation, прокрутите вниз и найдите зелёную кнопку Merge pull request. Она вливает вашу ветку в main.

Рядом с кнопкой есть стрелка выпадающего списка: GitHub умеет сливать тремя способами.

СпособЧто попадёт в mainКогда выбирать
Create a merge commitВсе коммиты ветки и ещё коммит слияния; история сохраняется целикомОсновной способ, мы пользуемся им
Squash and mergeОдин общий коммит вместо всех коммитов веткиКогда в ветке много мелких «wip»-коммитов (вернёмся к этому в финале)
Rebase and mergeКоммиты ветки по одному, без коммита слияния, история получается прямойПосле знакомства с rebase, он в модуле про чистую историю

Оставьте способ по умолчанию и нажмите Merge pull request. GitHub попросит подтверждения: появится кнопка Confirm merge и предложенное сообщение коммита слияния. Нажмите её. Страница PR станет фиолетовой с надписью Merged, а чуть ниже появится кнопка Delete branch. Нажмите и её: ветка feature/contacts на GitHub больше не нужна, вся её работа уже внутри main. Если удалили ветку случайно, в закрытом PR есть кнопка Restore branch.

Что сделать на своём компьютере

Слияние случилось на GitHub, у вас на компьютере ничего не изменилось. Это обязательный последний шаг, который новички пропускают: забрать результат и убрать мусор.

Терминал
$ git switch main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
$ git pull
From https://github.com/alex-ivanov/portfolio
   6b82c9b..8db0ddf  main       -> origin/main
Updating 6b82c9b..8db0ddf
Fast-forward
 index.html | 4 ++++
 1 file changed, 4 insertions(+)
$ git log --oneline --graph -5
*   8db0ddf Merge pull request #1 from alex-ivanov/feature/contacts
|\
| * 389da8c Добавить раздел «Контакты»
|/
* 6b82c9b Добавить ссылку на сайт в README
* e74f7d8 Дополнить подвал
$ git branch -d feature/contacts
Deleted branch feature/contacts (was 389da8c).
$ git fetch --prune
From https://github.com/alex-ivanov/portfolio
 - [deleted]         (none)     -> origin/feature/contacts

Разбор по строкам

  • Your branch is up to date with 'origin/main' — обманчивая строка. Git сравнивает с тем, что знал о GitHub в прошлый раз, и в сеть не ходит. Поэтому после слияния PR всё равно нужен git pull.
  • 6b82c9b..8db0ddf main -> origin/main — Git узнал, что на GitHub в main появился новый коммит 8db0ddf.
  • Fast-forward — перемотка: у вашего main своих новых коммитов не было, Git просто подвинул указатель вперёд.
  • git log --graph — видна «ромбовидная» форма: ветка с коммитом 389da8c влилась коммитом слияния 8db0ddf. Его сообщение Merge pull request #1 from ... подписал сам GitHub.
  • git branch -d — удалить локальную ветку; безопасный флаг -d откажет, если ветка не влита.
  • git fetch --prune — убрать из списка запомненную копию origin/feature/contacts, раз ветки на GitHub уже нет.

Подробно — в документации GitHub: Pull requests.

Практика у себя

  1. Откройте терминал в ~/projects/portfolio. Команда git status должна показать On branch main и nothing to commit, working tree clean. Выполните git pull.
  2. Создайте ветку: git switch -c feature/contacts. Команда ответит Switched to a new branch 'feature/contacts'.
  3. Добавьте в index.html перед подвалом раздел «Контакты» с вашей почтой. Проверьте git diff: в выводе четыре зелёные строки с плюсом.
  4. Закоммитьте: git add index.html, затем git commit -m "Добавить раздел «Контакты»".
  5. Отправьте ветку: git push -u origin feature/contacts. В конце вывода должна быть строка * [new branch] feature/contacts -> feature/contacts.
  6. Откройте репозиторий на GitHub, нажмите Compare & pull request, проверьте, что base — main, compare — feature/contacts. Заполните заголовок и описание по образцу и нажмите Create pull request.
  7. Откройте вкладки Commits и Files changed: коммит один, файл один.
  8. Вернитесь на Conversation, нажмите Merge pull request, затем Confirm merge и Delete branch.
  9. На компьютере выполните: git switch main, git pull, git branch -d feature/contacts, git fetch --prune.
  10. Откройте сайт https://alex-ivanov.github.io/portfolio/ (со своим логином). Через минуту-другую в нём появится раздел «Контакты».

Сайт на GitHub Pages обновляется после каждого изменения в main, поэтому слияние PR для него то же самое, что push в main в прошлом модуле. Иногда нужно подождать несколько минут.

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

  • git log --oneline --graph -5 показывает коммит слияния Merge pull request #1 from ... и ваш коммит «Добавить раздел «Контакты»» внутри ромба.
  • git branch показывает только main: ветка feature/contacts удалена.
  • git status сообщает Your branch is up to date with 'origin/main' и чистое дерево.
  • На GitHub у PR #1 пометка Merged, в index.html на main есть <section id="contacts">.
  • Вы можете объяснить, чем pull request отличается от git pull.

Частые ошибки

GitHub не показывает кнопку создания PR или пишет, что сравнивать нечего. Чаще всего base и compare выбраны одинаковые, например main и main, или в ветке нет новых коммитов. Выберите в compare свою ветку и убедитесь, что она запушена (git status не должен показывать ahead).

Забыли git pull после слияния. Вы начинаете новую ветку от старого main, а потом получаете конфликты на ровном месте. Привычка: слили на GitHub — сразу git switch main и git pull.

Ветка осталась висеть. Старые ветки копятся и мешают найти нужную: после слияния удаляйте их и на GitHub, и у себя.

fatal: The current branch feature/contacts has no upstream branch. Вы выполнили git push без -u в новой ветке. Git сам подсказывает исправление: git push --set-upstream origin feature/contacts (то же, что git push -u origin feature/contacts).

Что важно запомнить

  • Pull request — предложение влить ветку compare в ветку base; это функция GitHub, а не команда Git.
  • Цикл: ветка, коммиты, push, Compare & pull request, Merge pull request, Delete branch.
  • Новые коммиты, отправленные в ветку, сами попадают в открытый PR.
  • После слияния на GitHub у вас на компьютере: git switch main, git pull, git branch -d, git fetch --prune.
  • Мы сливаем способом «merge commit»; squash и rebase — позже.

Пока вы сами себе и автор, и единственный читатель: сами создали PR и сами нажали слияние. Настоящая польза PR начинается, когда изменения читает другой человек. Как оставлять замечания, отвечать на них и не превращать проверку в ссору — в следующем уроке.

На следующий урок