$ sudo teach IT
Модуль 8 · Финал · Урок 8.1

Финальный проект

Вы самостоятельно проведёте изменение по полному циклу, от задачи до релиза v1.1.0, и оформите профиль GitHub.

Практикум~60 минутНовичокполный циклпрофиль GitHub

Задание

Как оформить профиль GitHub, чтобы его не стыдно было показать: завести профильный README (репозиторий с именем вашего логина), закрепить лучшие репозитории и подписать каждый проект коротким описанием со ссылкой на сайт. Всё это вы сделаете во второй половине урока. А в первой пройдёте финальный проект: добавите на сайт новую страницу по тому же пути, по которому изменения попадают в настоящие команды.

Каждый шаг по отдельности вы уже умеете, но в жизни они идут подряд и без подсказок. Поэтому сначала чек-лист — попробуйте сами, а подробный разбор ждёт ниже, в выноске «Если застряли».

Задача: добавить на сайт страницу «Заметки» (blog.html) и ссылку на неё на главной. Содержимое страницы на ваш вкус, главное — провести её по такому маршруту:

  1. Issue. Заведите на GitHub issue «Добавить страницу «Заметки»» и запомните её номер (дальше он называется N).
  2. Ветка. Обновите main и создайте ветку feature/blog.
  3. Коммиты. Сделайте не меньше трёх: сама страница, первая заметка, ссылка в index.html. Один-два коммита с сообщением «wip» не страшны: следующий шаг их уберёт.
  4. Причёсывание. Соберите историю ветки в 2 понятных коммита через git rebase -i.
  5. Push и pull request. Отправьте ветку, откройте PR, в описании напишите Closes #N.
  6. Ревью. Откройте ветку во втором клоне portfolio-colleague и оставьте в PR комментарий к строке, как сделал бы коллега.
  7. Правки. Учтите замечание отдельным коммитом, добавьте запись о версии 1.1.0 в CHANGELOG.md и запушьте.
  8. Слияние. Нажмите Squash and merge и удалите ветку кнопкой Delete branch.
  9. Порядок у себя. Обновите main, уберите локальную ветку.
  10. Pages. Дождитесь обновления сайта и откройте blog.html по ссылке.
  11. Релиз. Поставьте аннотированный тег v1.1.0, отправьте его на GitHub и опубликуйте релиз.

Squash and merge и rebase -i: в чём разница

Squash and merge — один из трёх способов слияния PR на GitHub: все коммиты ветки склеиваются в один коммит на main. Заголовок и описание этого коммита GitHub предложит сам (обычно из названия PR), их можно поправить перед подтверждением. В main — одна задача, одна запись. Не путайте с squash в rebase -i: там вы склеиваете коммиты у себя до PR, а здесь GitHub склеивает их при слиянии.

Частая путаница: ветка «не слита», хотя PR закрыт

После Squash and merge на main появляется новый коммит с другим хешем, и ваших коммитов ветки Git в main не видит: git branch -d feature/blog ответит «not fully merged». Убедитесь, что PR помечен Merged, и удаляйте через git branch -D. Если PR не слит, -D удалит коммиты, которых больше нигде нет (вернуть их можно только через git reflog).

Разбор

Если застряли

Разбор каждого шага с настоящим выводом. Логин alex-ivanov, номера issue (#11) и PR (#12) и хеши у вас будут свои.

Шаги 1 и 2. Issue и ветка

На странице репозитория откройте вкладку Issues, нажмите New issue, впишите название «Добавить страницу «Заметки»» и создайте issue кнопкой Submit new issue. GitHub присвоит ей номер. Теперь ветка:

Терминал
$ git switch main
$ git pull
$ git switch -c feature/blog
Switched to a new branch 'feature/blog'

Шаг 3. Коммиты

Создайте blog.html с каркасом, как у остальных страниц, и закоммитьте. Минимальный вариант:

HTML · blog.html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>Заметки - Алекс Иванов</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>Заметки</h1>
  <p class="lead">Что я узнаю, пока учусь</p>
  <p><a href="index.html">На главную</a></p>
</body>
</html>

Потом добавьте первую заметку перед последним абзацем, а в index.html под ссылкой «Все мои проекты» — ссылку на новую страницу:

HTML · blog.html
  <article>
    <h2>Как я освоил Git</h2>
    <p>Сделал первые коммиты и выложил сайт на GitHub Pages.</p>
  </article>
HTML · index.html
    <p><a href="projects.html">Все мои проекты</a></p>
    <p><a href="blog.html">Заметки</a></p>

Допустим, вы спешили, и история получилась такой:

Терминал
$ git log --oneline -5
df67c6d ещё раз
2a9d04d Добавить ссылку на заметки
7433570 wip
da13cf7 Добавить страницу заметок
3390e52 Merge pull request #10 from alex-ivanov/docs/changelog

Шаг 4. Причёсываем историю

В ветке четыре коммита, значит, rebase -i HEAD~4. Редактор откроет список, сверху самые старые.

Терминал
$ git rebase -i HEAD~4
Конфиг · список в редакторе
pick da13cf7 Добавить страницу заметок
pick 7433570 wip
pick 2a9d04d Добавить ссылку на заметки
pick df67c6d ещё раз

Нужны два коммита: «страница» и «ссылка». «wip» и «ещё раз» правят blog.html, поэтому переставляем их под первый коммит с командой fixup. Сохраняем, закрываем редактор:

Конфиг · список после правки
pick da13cf7 Добавить страницу заметок
fixup 7433570 wip
fixup df67c6d ещё раз
pick 2a9d04d Добавить ссылку на заметки
Терминал
Successfully rebased and updated refs/heads/feature/blog.
$ git log --oneline -3
fc7e459 Добавить ссылку на заметки
0f6bdad Добавить страницу заметок
3390e52 Merge pull request #10 from alex-ivanov/docs/changelog

Хеши поменялись: rebase создаёт коммиты заново. Ветка не опубликована, переписывать её безопасно.

Шаг 5. Push и pull request

Терминал
$ git push -u origin feature/blog
...
remote: Create a pull request for 'feature/blog' on GitHub by visiting:
remote:      https://github.com/alex-ivanov/portfolio/pull/new/feature/blog
To https://github.com/alex-ivanov/portfolio.git
 * [new branch]      feature/blog -> feature/blog
branch 'feature/blog' set up to track 'origin/feature/blog'.

Обновите страницу репозитория и нажмите Compare & pull request. В заголовок впишите «Добавить страницу «Заметки»», в описание — что сделано и связь с issue:

Markdown · описание PR
Добавляет страницу «Заметки» и ссылку на неё на главной.

Closes #11

Нажмите Create pull request.

Шаг 6. Ревью из portfolio-colleague

Коллега забирает ветку и смотрит страницу у себя.

Терминал · папка portfolio-colleague
$ git fetch
From https://github.com/alex-ivanov/portfolio
 * [new branch]      feature/blog -> origin/feature/blog
$ git switch feature/blog
Switched to a new branch 'feature/blog'
branch 'feature/blog' set up to track 'origin/feature/blog'.

Откройте blog.html в браузере. Затем в PR на GitHub откройте вкладку Files changed, наведите курсор на строку с заметкой, нажмите синий значок комментария, напишите замечание, например «Добавь дату к заметке» — и выберите Start a review. Затем Review changes, вариант Comment (свой PR одобрить нельзя) и Submit review.

Шаг 7. Правки по ревью

Вернитесь в папку portfolio, ветка feature/blog. Добавьте под заголовком заметки строку с сегодняшней датой, например <p class="lead">20 ноября 2026</p>, и закоммитьте. Вторым коммитом допишите в CHANGELOG.md версию 1.1.0 над 1.0.0:

Markdown · CHANGELOG.md
## [1.1.0] - 2026-11-20
### Added
- Страница «Заметки» (blog.html) и ссылка на неё на главной.
Терминал
$ git commit -am "Добавить дату к заметке"
[feature/blog 28b9e01] Добавить дату к заметке
 1 file changed, 1 insertion(+)
$ git commit -am "Обновить CHANGELOG для версии 1.1.0"
[feature/blog 16ce524] Обновить CHANGELOG для версии 1.1.0
 1 file changed, 4 insertions(+)
$ git push
To https://github.com/alex-ivanov/portfolio.git
   fc7e459..16ce524  feature/blog -> feature/blog

Хватает простого git push: историю вы не переписывали. PR обновится сам. Ответьте на комментарий и нажмите Resolve conversation. Запись в CHANGELOG делаем до слияния: main защищён правилом, прямо в него не запишешь.

Шаг 8. Squash and merge

Внизу PR нажмите стрелку рядом с зелёной кнопкой Merge pull request, выберите Squash and merge, затем Confirm squash and merge. В PR появится метка Merged, а issue закроется. Нажмите Delete branch.

Шаг 9. Порядок у себя

Терминал
$ git switch main
Switched to branch 'main'
$ git pull
From https://github.com/alex-ivanov/portfolio
   3390e52..fafdf1d  main       -> origin/main
Updating 3390e52..fafdf1d
Fast-forward
 CHANGELOG.md |  4 ++++
 blog.html    | 18 ++++++++++++++++++
 index.html   |  1 +
 3 files changed, 23 insertions(+)
 create mode 100644 blog.html
$ git fetch --prune
From https://github.com/alex-ivanov/portfolio
 - [deleted]         (none)     -> origin/feature/blog
$ git branch -d feature/blog
error: the branch 'feature/blog' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature/blog'
$ git branch -D feature/blog
Deleted branch feature/blog (was 16ce524).

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

  • Fast-forward — на main один новый коммит; четыре коммита ветки превратились в одну запись.
  • fetch --prune — убирает локальную пометку origin/feature/blog для ветки, удалённой на GitHub.
  • not fully merged и -D — ожидаемо, как разобрано выше: PR слит, терять нечего.

Шаги 10 и 11. Pages, тег и релиз

Сайт обновляется после слияния сам, до 10 минут — нормально. Откройте https://alex-ivanov.github.io/portfolio/blog.html с вашим логином. Пока ждёте, ставьте тег: main уже свежий.

Терминал
$ git tag -a v1.1.0 -m "Версия 1.1.0: страница Заметки"
$ git tag
v1.0.0
v1.1.0
$ git push origin v1.1.0
To https://github.com/alex-ivanov/portfolio.git
 * [new tag]         v1.1.0 -> v1.1.0
$ git log --oneline --decorate -3
fafdf1d (HEAD -> main, tag: v1.1.0, origin/main) Добавить страницу «Заметки» (#12)
3390e52 (tag: v1.0.0) Merge pull request #10 from alex-ivanov/docs/changelog
24e7597 Добавить CHANGELOG

Заголовок squash-коммита здесь — тот, что предложил GitHub: название PR и его номер. Если вы поправили его при слиянии, у вас будет свой.

На странице репозитория нажмите Releases (справа от списка файлов), затем Draft a new release. В выпадающем списке Choose a tag выберите v1.1.0, в поле Release title напишите v1.1.0, нажмите Generate release notes и Publish release.

Тег ставят на свежий main

Тег ложится на коммит, на котором вы стоите: до git pull или в другой ветке он попадёт не на squash-коммит. Проверка: git log --oneline --decorate -1 должен показать tag: v1.1.0 рядом с последним коммитом main.

README-профиль

README-профиль на GitHub — это визитка вверху вашей страницы github.com/alex-ivanov. Он показывается, если есть публичный репозиторий с тем же именем, что и ваш логин, а в корне лежит непустой README.md.

  1. Вверху справа нажмите +, затем New repository.
  2. В поле Repository name впишите ровно ваш логин, например alex-ivanov.
  3. Выберите Public и переведите переключатель Add README в положение On. Здесь локального проекта нет, поэтому README удобно создать сразу (для сайта мы этого не делали: история уже была).
  4. Нажмите Create repository, затем Edit README над правой колонкой.
  5. Напишите текст, нажмите Commit changes. Откройте свой профиль: текст уже там.

Что писать? Коротко, по делу, без паролей и без лишних личных данных. Работодатель смотрит профиль секунд тридцать:

Markdown · README.md
# Привет, я Алекс

Начинающий фронтенд-разработчик: HTML, CSS и Git. Делаю свои первые сайты.

## Чем занимаюсь
- Изучаю HTML, CSS и Git
- Веду сайт-визитку: https://alex-ivanov.github.io/portfolio/

## Связаться
- Почта: alex@example.com

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

  • # и ## — заголовки первого и второго уровня.
  • - в начале строки — пункт маркированного списка.
  • Адрес сайта GitHub превратит в ссылку сам.

Показать почту или нет

Почту в README видят все, включая рассылочных ботов. Если не хотите, оставьте ссылку на профиль: контакт через GitHub тоже контакт.

Портфолио в порядке

Портфолио на GitHub — это не отдельная страница, а то, как выглядят ваши репозитории. Три вещи делают его аккуратным.

1. Описание и ссылка у проекта. Адрес сайта в блоке About вы вписали, когда публиковали визитку. Снова нажмите шестерёнку рядом с About (подсказка Edit repository metadata), проверьте описание, например «Сайт-визитка: HTML, CSS, учебный проект по Git», и добавьте несколько тем (Topics), например html, css, git (строчными буквами). Нажмите Save changes.

2. Закреплённые репозитории. Откройте профиль (Your profile в меню по клику на аватар), нажмите Customize your pins, выберите нужные репозитории — закрепить можно до шести — и нажмите Save pins. Закрепите portfolio и то, чем гордитесь.

3. README у каждого закреплённого проекта. Минимум: что это, как посмотреть, чему научились. В README.md проекта portfolio описание и ссылка на сайт уже есть — допишите пару строк о том, чему научились (через ветку и PR: main под правилом).

Самопроверка

Пройдитесь по списку на GitHub и у себя в терминале. Всё отмечено — финал сдан.

  • Issue «Добавить страницу «Заметки»» закрыта и содержит ссылку на PR.
  • PR слит способом Squash and merge, ветка feature/blog удалена на GitHub и у вас.
  • git log --oneline --decorate -3 показывает последний коммит main с тегом v1.1.0 и названием вашего PR.
  • git status сообщает nothing to commit, working tree clean, а в git branch нет ветки feature/blog.
  • Страница blog.html открывается по адресу на github.io, ссылка на неё есть на главной.
  • В разделе Releases есть релиз v1.1.0, в нём заметки к выпуску.
  • В профиле виден README-профиль и закреплённый portfolio, у репозитория заполнены описание и ссылка на сайт.

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

Issue не закрылась после слияния. В описании PR «closes 11» без решётки или слияние шло не в main. Нужен вид Closes #11 и PR в ветку по умолчанию. Закройте issue руками кнопкой Close issue.

git push после rebase отклонён (rejected ... non-fast-forward): вы причёсывали ветку уже после первого push. Нужен git push --force-with-lease в свою ветку.

Pages показывает старую страницу. Подождите до 10 минут и обновите страницу с Ctrl+F5. Если и час спустя ничего не изменилось, откройте Settings, раздел Pages, и проверьте, что источник — ветка main.

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

  • Цикл настоящей работы: issue, ветка, коммиты, причёсывание, push, PR, ревью, правки, слияние, релиз.
  • rebase -i и squash на GitHub — разные вещи в разных местах: первое чистит вашу ветку до PR, второе склеивает PR при слиянии.
  • После Squash and merge локальную ветку удаляют через git branch -D, предварительно убедившись, что PR слит.
  • Тег ставят на свежий main после git pull, а на GitHub отправляют отдельно: git push origin v1.1.0.
  • Профильный README — публичный репозиторий с именем логина и непустым README.md.
  • Профиль: About с описанием и ссылкой, до шести закреплённых репозиториев, README у каждого проекта.

Что дальше

Проект готов, версия выпущена, профиль оформлен. Остался вопрос, который задаёт каждый, закончив курс: что дальше и где держать всё это под рукой? В последнем уроке соберём все команды курса в одну шпаргалку и наметим следующие шаги.

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