GitHub — Примеры
Пример 1 — Пуш, перезаписывающий опубликованную историю
Разработчик приводит коммиты в порядок, пересобирая основную линию локально, и потом отправляет её. Копия товарища по команде теперь расходится с удалённым репозиторием. Покажите, что сделал пуш, затем — как опубликовать аккуратную историю, не перезаписывая то, что у других уже есть.
git log --oneline origin/main..main # что добавляет мой локальный main
git push --force origin main # заменяет опубликованную ссылку
# товарищ: git pull -> "diverged" и задвоенный коммит
Решение
git fetch origin
git rebase origin/main # переиграть мои коммиты поверх их
git push origin main # fast-forward, ничто не заменяется
# вместо этого для новой работы: пуш ветки и pull request
git push -u origin fix/142-coupon
Удалённый репозиторий хранит те же объекты, что и локальный, поэтому force-push не добавляет один новый коммит. Он выбрасывает ссылку, на которой держались все остальные, и направляет её в другое место. Переписывать собственные коммиты, ещё никому не отправленные, безвредно, а вот переписывание ссылки, которую другие уже забрали, обходится им в ручное восстановление. Отсюда и правило, которое применяет пример: порядок наводите в приватной копии, rebase делайте поверх опубликованного, а всё, что меняет опубликованную историю, проводите через pull request — там изменение видно.
Пример 2 — Pull request на шестьдесят файлов
Ветка накопила три несвязанных изменения за две недели. В pull request’е шестьдесят изменённых файлов; первый рецензент оставляет комментарий про форматирование и останавливается. Улучшите ревью, не меняя то, что поставляется.
git switch -c feat/dashboard # ответвлена две недели назад
git push -u origin feat/dashboard
# хостинг: pull request в main, 60 изменённых файлов, задача не связана
Решение
git switch -c feat/dashboard-layout main # одна забота на ветку
git switch -c fix/142-expired-coupon main
git switch -c chore/upgrade-linter main
git push -u origin fix/142-expired-coupon
# хостинг: открыть pull request, тело "Closes #142", нужно одно одобрение
Дифф, обсуждение и решение живут в pull request’е, поэтому размер его определяет качество ревью, а не остаётся деталью git. Три маленьких pull request’а читаются за минуты, каждый ссылается на задачу, объясняющую, зачем изменение существует, и каждый можно слить, не таща за собой два других. Разделение кладёт рассуждение туда, где сопровождающий найдёт его позже, ведь приватный разговор о дизайне не оставляет в репозитории ничего. А привычку к маленькому диффу делает обеспеченной принудительно, а не просто желательной, защищённая основная ветка.