Git
Шпаргалка по командам и правила оформления коммитов.
В общем решил так же написать шпаргалку по Git, т.к часто многое вылетает из головы между сессиями и кодинга, так же в конце прикрепил правила оформления коммитов для себя, возможно вам тоже поможет в сопровождении своих проектов, т.к недавно обновил документ по командам OpenSUSE с коммитом "chore(docs): update bla bla bla", в общем не делайте так, делайте правильно.
Базовые команды
git init # создать репозиторий в текущей папке
git clone <url> # склонировать существующий
git status # что вообще происходит: что изменено, что staged
git status --short # то же самое, но одной строкой на файл — быстрее читать
git add <file> # добавить файл в staging (подготовить к коммиту)
git add . # добавить всё изменённое и новое в текущей папке
git add -A # добавить вообще всё по всему репозиторию
git commit -m "сообщение" # закоммитить staged-изменения
git push # отправить коммиты в origin
git pull # забрать и применить изменения из origin (fetch + merge)
Что важно помнить про add: если просто сделал git commit -a, staged будут только отслеживаемые файлы. Новые файлы без git add в коммит не попадут. Я вечно про это забываю.
Ветки
git branch # показать локальные ветки
git branch -a # показать вообще все (и remote тоже)
git branch <name> # создать ветку, но НЕ переключиться в неё
git checkout <name> # переключиться в ветку (старый синтаксис)
git switch <name> # переключиться в ветку (новый, с Git 2.23+)
git checkout -b <name> # создать и сразу переключиться
git switch -c <name> # то же самое, но новым синтаксисом
git merge <branch> # влить указанную ветку в текущую
git rebase <branch> # переложить коммиты текущей ветки поверх указанной
git branch -d <name> # удалить локальную ветку (безопасно: только если всё слито)
git branch -D <name> # удалить локальную ветку (жёстко, даже если не слито)
git push origin --delete <name> # удалить ветку на remote
Я обычно использую switch вместо checkout — меньше путаницы, потому что checkout умеет слишком много всего (переключение веток, восстановление файлов, создание веток...). switch делает ровно одно дело.
Исправление ошибок
Ситуации, в которые я попадаю регулярно: закоммитил не то, не туда, или с кривым сообщением.
# --- Поправить последний коммит ---
git commit --amend -m "новое сообщение" # изменить сообщение последнего коммита
git commit --amend --no-edit # добавить забытые изменения в последний коммит,
# не трогая сообщение
# --- Отменить staged (убрать из staging, но сохранить изменения) ---
git restore --staged <file> # новый синтаксис (Git 2.23+)
git reset HEAD <file> # старый синтаксис, всё ещё работает
# --- Откатить изменения в файле (сбросить до последнего коммита) ---
git restore <file> # новый синтаксис
git checkout -- <file> # старый синтаксис
# --- Откатить коммиты ---
git reset --soft HEAD~1 # отменить последний коммит, оставить изменения в staging
git reset --mixed HEAD~1 # отменить коммит, снять staging, но оставить изменения в файлах
git reset --hard HEAD~1 # отменить коммит и ВСЁ удалить (осторожно!)
git revert <commit-hash> # создать новый коммит, отменяющий указанный (безопасно для shared веток)
# --- Временно спрятать изменения ---
git stash # спрятать все незакоммиченные изменения
git stash push -m "описание" # спрятать с комментарием (через месяц иначе не вспомню что там)
git stash pop # вернуть последний stash и удалить его из списка
git stash list # посмотреть всё что спрятано
git stash drop stash@{n} # удалить конкретный stash
# --- Перенести коммит из другой ветки ---
git cherry-pick <commit-hash> # применить чужой коммит к текущей ветке
Важное про reset vs revert: reset переписывает историю, revert добавляет новый коммит. Если ветка уже запушена и её кто-то мог склонировать — только revert. Если ветка локальная и кроме меня её никто не видел — reset ок.
Просмотр истории
git log # классика
git log --oneline # каждый коммит в одну строку — для быстрого обзора
git log --oneline --graph --all # дерево всех веток, удобно перед merge
git log --oneline -n 10 # только последние 10 коммитов
git log --grep="pattern" # найти коммиты по тексту в сообщении
git log -S "строка кода" # найти коммиты, где строка была добавлена или удалена (pickaxe)
git diff # что изменилось, но ещё не staged
git diff --staged # что staged и уйдёт в следующий коммит
git diff <branch1>..<branch2> # разница между ветками
git blame <file> # кто последний трогал каждую строку (и в каком коммите)
git show <commit-hash> # показать полный диф конкретного коммита
Мой любимый алиас, без которого уже не могу:
git log --oneline --graph --all -n 20
Показывает полную картину проекта за последние 20 коммитов. Надо бы только не спешить и чаще ее применять, возможно и ошибок было бы меньше...
Удалённые репозитории
git remote -v # посмотреть все remote
git remote add <name> <url> # добавить новый remote
git remote remove <name> # удалить
git fetch <remote> # забрать изменения, но не применять
git pull <remote> <branch> # fetch + merge в одной команде
git push -u origin <branch> # запушить ветку и запомнить upstream (чтобы потом просто git push)Conventional Commits — правила оформления коммитов
Конвенция, по которой живёт большинство проектов в 2026 году. Спецификация: conventionalcommits.org v1.0.0. Штука не новая, но до сих пор актуальная — ничего не поменялось с момента принятия спеки, и менять, судя по всему, не планируют.
Суть: коммит-сообщение пишется так, чтобы его могла прочитать и машина (для автосборок, changelog'ов, определения версии), и человек.
Структура
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Вот так в одну строку:
docs(git): add stash section to cheatsheet
Или с телом:
fix(auth): handle expired refresh token
The token refresh was silently failing when the refresh endpoint
returned 401, leaving the user stuck on a blank screen. Now we
catch the error and redirect to login.
Closes #142Типы (type)
Вот полный список. Жирным выделил те, которыми реально пользуюсь.
| Тип | Назначение |
|---|---|
feat | Новая функциональность. Тянет за собой minor-версию при авторелизе. |
fix | Исправление бага. Тянет patch-версию. |
docs | Только документация. Никаких изменений кода. |
style | Форматирование, пробелы, точки с запятой — всё что не меняет логику. |
refactor | Переписал код, но поведение не изменилось. Ни багов, ни фич. |
perf | Оптимизация производительности. |
test | Добавил или поправил тесты. |
build | Система сборки, зависимости (npm, cargo, pip, и т.д.). |
ci | CI/CD пайплайны, конфигурация деплоя. |
chore | Всё остальное: обновил либу, поправил .gitignore, подтёр мусор. Не меняет production-код. |
revert | Откат предыдущего коммита. Сообщение: revert: <original-commit-message>. |
Scope (необязательно)
Уточняет, какую часть проекта затронул коммит. Пишется в скобках сразу после типа:
feat(auth): add OAuth2 login
fix(ui): correct button alignment on mobile
docs(api): document v2 endpoints
Scope — не тип, и не описание. Он отвечает на вопрос «где?», а не «что?».
Описание (description)
- На английском. Даже если весь проект на русском — сообщения коммитов пишутся на английском. Так принято в open-source, и так работает автосборка changelog'ов.
- В повелительном наклонении (imperative mood): «add feature», а не «added feature» или «adds feature». Проверка: сообщение должно продолжать фразу «If applied, this commit will...».
- Без точки в конце.
- До 72 символов (по возможности, не догма).
BREAKING CHANGE (критично!)
Если коммит ломает обратную совместимость, это нужно обозначить явно. Два способа:
Способ 1 — восклицательный знак после типа/scope:
feat(api)!: drop support for legacy tokens
Способ 2 — футер BREAKING CHANGE:
feat(api): drop support for legacy tokens
BREAKING CHANGE: All clients must migrate to OAuth2 tokens.
The /v1/auth endpoint is removed.
Оба варианта корректны по спеке. ! короче, но футер даёт больше места для объяснения миграции.
Примеры: правильно и неправильно
Правильно:
feat: add dark mode toggle
fix(parser): handle empty input gracefully
docs: explain branching strategy
chore: bump zola to 0.20.0
refactor(database): extract connection pool to separate module
Неправильно — и почему:
chore(docs): update git.md
→ docs — это тип коммита, а не scope. Не надо запихивать один тип в scope другого. Если меняешь документацию, пиши docs: update git.md. Если это правда chore (поправил сборку, конфиг, что-то около), то scope — не docs, а что-то другое, либо без scope вообще.
feat: added new button
→ «added» — прошедшее время. Правильно: «add new button».
Feat: add new button
→ Тип всегда lowercase. feat, не Feat.
fix: исправил баг с кодировкой
→ Описание на русском. Пиши на английском. Даже если кажется что «никто кроме меня не увидит» — через месяц сам себе спасибо скажешь.
Update file
→ Нет типа. git log без типа выглядит как свалка. Минимум: chore: update file.
Зачем вообще это всё
- Автоматический changelog. Инструменты типа
git-cliff,release-please,semantic-releaseпарсят историю коммитов и генерируют CHANGELOG.md сами. Без конвенции — не могут. - Поиск по истории.
git log --grep="^feat"— все фичи за раз.git log --grep="^fix"— все багфиксы. - Человекочитаемость. Открываешь
git log --onelineи сразу понятно, что происходило, без вчитывания в каждое сообщение. - Semantic Versioning на автомате.
fix:→ patch,feat:→ minor,BREAKING CHANGE:→ major. CI делает это сам.
Проверка перед коммитом
Перед git push прогоняю глазами последние 3-5 коммитов:
git log --oneline -5
Если вижу что-то вроде chore(docs): или сообщение на русском — правлю через git rebase -i или git commit --amend, пока не поздно.
Буду дополнять по мере того, как выстрелю себе в ногу новым способом.