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