📱 Подписаться
IT и цифровая трансформация

GIT: как ломать и чинить историю правильно (2 часть)

📰 Habr 👁️ 1 просмотров

ivalexander2 часа назад

GIT: как ломать и чинить историю правильно (2 часть)

Время на прочтение5 минОхват и читатели2.8KБлог компании Wildberries & RussGit*ТуториалВсем привет! Впрошлой части мы разобрали основные инструменты приведения истории GIT в порядок, в этот раз мы постараемся ответить на ряд вопросов, которые позволят нам чуть глубже понимать механизмы работы с историей коммитов и даже попытаемся провести настоящее детективное расследование и выйти на авторов, которые внесли те или иные изменения в код!

Содержание

• git push -f — наш союзник или враг?
• git commit --amend — не делаем много однотипных коммитов
• git blame — учимся анализировать статистику, смотреть историю конкретных участков кода

git push -f — наш союзник или враг?

Часто приходилось слышать мнение, что git push -f — это наш враг номер 1 и что никогда нельзя использовать эту команду, так ли это? Попробуем выяснить. 

git push -f — это force push, команда, которая позволяет переписать историю коммитов в remote ветке. Звучит страшно? На самом деле, не очень, но необходимо понимать и оценивать риски:

• принудительно отправляет изменения в remote
• игнорирует расхождения истории
• перезаписывает удалённую ветку💡«ломает правила ради результата»

Рассмотрим, в каких сценариях можно использовать git push -f:

• после rebase,
• после commit --amend,
• после rebase -i.В общем, в тех ситуациях, когда локальный commit hash не совпадает с тем, что в удалённой ветке.

Когдаточно можноиспользовать: 

• работаешь один в ветке,
• feature-ветка,
• чистишь историю перед PR/MR.Как и с любым другим инструментом, использование этого несёт в себе определенные риски, важно понимать, что в этих сценариях использование git push -f оправдано и польза превышает риск.

Когдаточно нельзяиспользовать:

• общая ветка,
• несколько разработчиков,
• кто-то уже подтянул изменения.В этих сценариях риск не оправдан совсем. Что же может пойти не так?

• исчезнут чужие коммиты,
• сломается история,
• люди не смогут сделать pull.Начнётся полнейший хаос, и коллеги тебе за такое «спасибо» не скажут.

Как используем:

• только в своей ветке,
• убедиться, что никто не работает с ней,
• предупредить команду (если нужно),
• когда ты действительно понимаешь, что делаешь.Можем себя обезопасить: у этой команды есть «старший брат» - git push --force-with-lease. 

git push --force-with-lease — перед отправкой данных в remote и переписыванием истории проверяет «а не закинул ли кто-то чего-то своего в эту ветку?». Можно назвать это умным git push -f, и данная команда — твой верный союзник.

Подведём итоги: 

• мощный инструмент,
• дает контроль над историей,
• безопасен при правильном использовании.Важно

• если не уверен — не используй push -f,
• если ветка твоя личная — push -f твой союзник для чистой истории.

git commit --amend — не делаем много однотипных коммитов

Если вы частенько задавались вопросами: «можно ли как-то исправить последний коммит?» или «можно ли не делать кучу однотипных коммитов на ревью?», то у меня для вас замечательная новость! У нас есть команда git commit --amend. Попробуем разобраться, как это работает.

Что это вообще такое?

Команда git commit --amend позволяет создать новый коммит на базе последнего коммита. После введения команды можно отредактировать содержимое коммита и сообщение. Так как меняется и содержимое, и метаданные, то GIT пересчитывает hash, поэтому после внесения изменений требует git push -f для отправки данных в remote.

В каких сценариях может быть полезен?

• забыл добавить файл,
• опечатка в сообщении,
• мелкая правка сразу после commit,
• must have для мелких изменений в процессе проведения код-ревью, на каждое изменение можно не создавать отдельный коммит, достаточно добавить изменения в последний.Как и с любыми другими инструментами редактирования истории, здесь есть свои ограничения на использование. 

Когда точно нельзя использовать:

• commit уже у других,
• общая ветка,
• main / develop.💡можно сломать историю

Плюсы использования инструмента:

• чистая история,
• нет “fix fix fix”,
• аккуратный PR/MR.Разберём на графическом примере для понимания, как это работает:

Есть некоторая история коммитов во feature-ветке, наблюдаем, что в последнем коммите ужасное сообщение и мечтаем поправить его:

• выполняем команду git commit --amend
• открывается редактор сообщения
• вводим необходимое сообщение, сохраняем и закрываем
• создается новый коммит на базе последнего, но уже с новым сообщениемИтог

• быстрый способ поправить commit,
• идеально для последних изменений,
• делает историю аккуратной.

git blame — учимся анализировать статистику, смотреть историю конкретных участков кода

Вам когда-нибудь хотелось узнать историю конкретного участка кода? Узнать, кто, когда и зачем написал определённую строку, удаление которой приводит к краху всего проекта? Если для вас эти вопросы актуальны, то добро пожаловать в мир построчной аналитики файлов с помощью инструментов GIT. 

Разберём команду git blame и посмотрим, с какими ещё командами её можно использовать, чуть-чуть залезем в bash и посмотрим на реальную магию.

Что это вообще такое?

• показывает, кто изменил каждую строку,
• показывает commit и дату,
• даёт быстрый доступ к истории.💡история на уровне строки

Пример вывода команды:

git blame file.ts

a1b2c3d4 (alex 2024-01-10 12:30:00) const user = getUser()
e5f6g7h8 (ivan 2024-01-11 09:15:00) if (!user) return nullВ выводе можно увидеть следующую информацию:

• hash коммита
• автор
• дата
• строкаДля чего это может быть полезно:

• понять, кто писал код,
• понять, когда добавили баг,
• быстро найти commit,
• выйти на автора.Важно понимать:

Эта команда не для обвинения вашего коллеги, а способ нахождения контекста проблемы. Удобно использовать в паре с командой git show.

git show позволяет просмотреть подробную информацию по изменениям в файлах по хэшу коммита.

Сценарий использования:

• в файле был обнаружен какой-то странный код
• if (isEnabled && !isEnabled) 🤡
• делаем git blame file.ts
• git show <hash>Profit!Находим контекст определённой строки и понимаем, какая логика была добавлена вместе с ней.

У команды есть несколько флагов, чтобы облегчить нам жизнь:

• git blame -L 10,20 file.ts — позволяет задать диапазон строк (если нет смысла просматривать весь файл);
• git blame -w file.ts — позволяет игнорировать пробелы, улучшает вывод, так как не учитывает изменения beautify code.Так как вывод команды — это фактически полноценная таблица с данными, то для анализа мы можем использовать awk, и тут начинается магия! Чтобы разобрать, как работает awk, нужна отдельная статья, поэтому просто посмотрим несколько кейсов.

Анализируем, кто чаще вносил изменения в файл, делаем красивый вывод в таблице, где отобразим количество написанных строк и автора изменений:

git blame file.ts | awk '{print $2}' | sort | uniq -c | sort -nr

120 Alex
45 Ivan
10 SergeyСделаем задачу ещё интереснее — выяснить, какое количество строк в файле являются самыми древними. Мы можем это сделать с помощью тех же самых инструментов:

git blame file.ts | awk '{print $3}' | sort | uniq -c

12 2021-03-10 44 2022-07-15 87 2025-01-12 Можем наблюдать здесь следующие данные:

• количество строк
• датаСтатистика может помочь определить, насколько часто вносят изменения в файл.

На самом деле, комбинируя различные bash команды и git blame, можно вытаскивать из файлов полезную информацию и проводить настоящие расследования. 

Ну и, конечно же, рассмотрим плюсы этой команды:

• быстрый анализ кода,
• помогает в дебаге,
• находит владельца логики.Минусы (куда же без них):

• может вводить в заблуждение,
• форматирование ломает blame,
• не показывает всю историю.Итог:

• инструмент анализа, а не обвинения,
• показывает «кто и когда»,
• всегда проверяй commit.

Общий итог

На самом деле, я не имею ничего против UI решений для работы с GIT. В современных редакторах графический интерфейс довольно удобен и практичен для повседневных задач. Но иногда я замечал, что разработчики не до конца понимают, как устроен и работает GIT в целом, что может приводить к ряду проблем.

Я хотел показать, что терминальный GIT не так страшен, в сложных сценариях, таких как rebase, recovery после неудачного merge, аналитика кода зачастую дает больше контроля и понимания происходящего.

Иногда UI помогает быстро наломать дров, а исправлять последствия всё равно приходится через терминал.

Делитесь своим опытом и задавайте вопросы в комментариях!Теги:• GIT
• rebase
• commit
• merge
• git pushХабы:• Блог компании Wildberries & Russ
• Git

Получайте больше инсайтов о систематизации бизнеса

Подписывайтесь на Telegram-канал Business Operations — ежедневные материалы о бизнес-процессах, операционном управлении и повышении эффективности

💬 Подписаться на канал