Working Directory → Staging Area (Index) → Local Repository → Remote Repository
(файлы) (git add) (git commit) (git push)
Working Directory: файлы на диске, текущее состояние.
Staging Area: промежуточная зона, которая определяет что попадёт в следующий коммит.
Commit: снимок состояния проекта. Неизменяемый, имеет хеш (SHA).
Branch: указатель на коммит. Дешёвый, просто ссылка, не копия.
HEAD: указатель на текущий коммит/ветку, то где ты сейчас.
Remote: удалённый репозиторий (GitHub, GitLab, etc.).
Начальная настройка
git config --global user.name "Имя Фамилия"git config --global user.email "email@example.com"# Редактор по умолчаниюgit config --global core.editor "nvim"# Ветка по умолчаниюgit config --global init.defaultBranch main
# Автоматически настраивать upstream при pushgit config --global push.autoSetupRemote true
# Красивый diffgit config --global diff.algorithm histogram
# Авторебейз при pullgit config --global pull.rebase true
# Rerere — запоминает разрешение конфликтовgit config --global rerere.enabled true
Основные команды
Создание и клонирование
git init # инициализация в текущей директорииgit clone <url> # клонировать репозиторийgit clone <url> <dir> # клонировать в конкретную директориюgit clone --depth 1 <url> # shallow clone (только последний коммит)
Состояние и информация
git status # текущее состояниеgit status -s # краткий форматgit log --oneline # история коммитов (кратко)git log --oneline --graph --all # граф всех ветокgit log -p # история с diff-амиgit log --since="2 weeks ago"# за последние 2 неделиgit log --author="Имя"# коммиты конкретного автораgit log -- path/to/file # история конкретного файлаgit show <commit> # посмотреть конкретный коммитgit blame <file> # кто какую строку менял
Добавление и коммит
git add <file> # добавить файл в staginggit add -p # интерактивный staging по кускам (hunk)git commit -m "message"# коммит с сообщениемgit commit # коммит — откроется редакторgit commit -am "message"# add + commit для tracked файловgit commit --amend # изменить последний коммит
Diff
git diff # изменения в working dir (не staged)git diff --staged # изменения в staging (будут в коммите)git diff main..feature # разница между веткамиgit diff HEAD~3 # изменения за последние 3 коммитаgit diff --stat # только статистика (какие файлы, сколько строк)git diff --name-only # только имена изменённых файлов
Ветки
git branch # список локальных ветокgit branch -a # все ветки (включая remote)git branch <name> # создать веткуgit branch -d <name> # удалить ветку (safe)git branch -D <name> # удалить ветку (force)git branch -m <old> <new> # переименовать веткуgit switch <branch> # переключиться на веткуgit switch -c <branch> # создать и переключитьсяgit switch - # вернуться на предыдущую ветку
Remote
git remote -v # список remote-овgit remote add origin <url> # добавить remotegit fetch # скачать изменения (без merge)git fetch --prune # + удалить ссылки на удалённые веткиgit pull # fetch + merge (или rebase, если настроено)git push # отправить на remotegit push -u origin <branch> # push + установить upstreamgit push origin --delete <branch> # удалить ветку на remote
Merge и Rebase
# Merge — создаёт merge-коммит, сохраняет историюgit merge <branch>
# Rebase — переносит коммиты поверх другой ветки, линейная историяgit rebase main # перебазировать текущую ветку на main# Интерактивный rebase — переупорядочить, склеить, отредактировать коммитыgit rebase -i HEAD~3 # последние 3 коммита# pick — оставить коммит# squash — склеить с предыдущим (сохранить сообщение)# fixup — склеить с предыдущим (выбросить сообщение)# reword — изменить сообщение# drop — удалить коммит# Отменаgit merge --abort # отменить mergegit rebase --abort # отменить rebase
Когда merge, когда rebase:
rebase: для своих feature-веток, чтобы подтянуть main. Линейная, чистая история.
merge: для вливания feature в main. Сохраняет контекст “когда что влили”.
Никогда не rebase то, что уже запушено и используется другими.
Stash
git stash # спрятать текущие измененияgit stash -m "описание"# спрятать с описаниемgit stash -u # включая untracked файлыgit stash list # список stash-ейgit stash pop # достать последний stash + удалитьgit stash apply # достать последний stash (не удалять)git stash drop # удалить последний stashgit stash pop stash@{2}# достать конкретный stash
Отмена изменений
# Убрать файл из staging (не трогая содержимое)git restore --staged <file>
# Откатить файл к последнему коммиту (потеря изменений!)git restore <file>
# Откатить коммит, создав новый "обратный" коммит (safe)git revert <commit>
# Сдвинуть HEAD назад (осторожно)git reset --soft HEAD~1 # убрать коммит, изменения в staginggit reset --mixed HEAD~1 # убрать коммит, изменения в working dirgit reset --hard HEAD~1 # убрать коммит + изменения (потеря данных!)
--soft → коммит убран, файлы в staging (готовы к re-commit)
--mixed → коммит убран, файлы в working dir (надо git add снова)
--hard → коммит убран, файлы удалены (как будто ничего не было)
Reflog: страховочная сетка
git reflog # история всех перемещений HEADgit reset --hard HEAD@{5}# вернуться к состоянию 5 шагов назад
Reflog хранит всё, даже после reset --hard. Если потерял коммиты, ищи их тут.
git tag v1.0.0 # лёгкий тегgit tag -a v1.0.0 -m "Release"# аннотированный тегgit push origin v1.0.0 # push тегаgit push origin --tags # push всех тегов
Dev-флоу: ежедневная работа
Feature Branch Workflow
Основной паттерн для работы в команде:
# 1. Обновить maingit switch main
git pull
# 2. Создать feature-веткуgit switch -c feature/user-auth
# 3. Работать, коммититьgit add -p # staging по кускам — контролируешь что попадёт в коммитgit commit -m "add login endpoint"# ... ещё работа ...git commit -m "add JWT validation"# 4. Периодически подтягивать maingit fetch
git rebase origin/main # перебазировать свои коммиты поверх актуального main# 5. Перед push: навести порядок в коммитахgit rebase -i origin/main # squash/fixup мелких коммитов# 6. Pushgit push
# 7. Создать Pull Request (через GitHub/GitLab UI или CLI)gh pr create --fill # GitHub CLI
Паттерн: быстрый фикс на main
git stash -m "текущая работа"# спрятать незавершённую работуgit switch main
git pull
git switch -c fix/typo-in-readme
# ... фикс ...git commit -am "fix typo in README"git push
git switch - # вернуться на предыдущую веткуgit stash pop # достать свою работу
Паттерн: git add -p (частичный staging)
Самая полезная команда для чистых коммитов. Позволяет добавить в коммит только часть изменений файла:
git add -p
# y — добавить этот кусок# n — пропустить# s — разбить на более мелкие куски# e — ручное редактирование куска# q — выйти
Зачем: один файл может содержать изменения для разных логических задач. add -p позволяет разделить их по разным коммитам.
Паттерн: fixup-коммиты
Нашёл ошибку в коммите, который сделал 3 коммита назад:
# Исправить файл, затем:git commit --fixup <commit-hash> # создаст коммит "fixup! original message"# Перед push — склеить fixup-ы автоматически:git rebase -i --autosquash origin/main
Разрешение конфликтов
# При merge/rebase возникает конфликт:<<<<<<< HEAD (или текущая ветка)код из твоей ветки
=======код из другой ветки
>>>>>>> feature/other
# 1. Отредактировать файл — оставить нужный код, убрать маркеры# 2. git add <file># 3. git rebase --continue (или git merge --continue)
Инструменты для разрешения конфликтов:
git mergetool # откроет настроенный merge-tool# или настроить nvim как mergetool:git config --global merge.tool nvimdiff
[alias]s=status -s
l = log --oneline -20
lg = log --oneline --graph --all -30
d = diff
ds = diff --staged
co = switch
cb = switch -c
aa = add --all
ap = add -p
cm = commit -m
ca = commit --amend --no-edit
pu = push
puf = push --force-with-lease
pl = pull
rb = rebase
rbi = rebase -i
cp = cherry-pick
st = stash
stp = stash pop
last = log -1 --stat
undo = reset --soft HEAD~1
unstage = restore --staged
wip = "!git add -A && git commit -m 'wip'"
gone = "!git fetch -p && git branch -vv | grep 'gone]' | awk '{print $1}'"
Использование:
git s # git status -sgit l # последние 20 коммитовgit lg # граф ветокgit ap # git add -pgit cm "add feature"# git commit -m "add feature"git undo # отменить последний коммит (изменения в staging)git gone # показать ветки, удалённые на remote
GitHub / GitLab CLI
GitHub CLI (gh)
# Pull Requestsgh pr create --fill # создать PRgh pr list # список PRgh pr view 123# посмотреть PRgh pr checkout 123# скачать PR в локальную веткуgh pr merge 123 --squash # merge PR# Issuesgh issue create --title "Bug"# создать issuegh issue list # список issues# Reposgh repo clone owner/repo # клонироватьgh repo fork # форкнуть
GitLab CLI (glab)
glab mr create --fill # создать MRglab mr list # список MRglab mr checkout 123# скачать MRglab ci status # статус CI/CD
Продвинутые приёмы
Bisect: поиск коммита с багом
git bisect start
git bisect bad # текущий коммит — баг естьgit bisect good <commit> # этот коммит — баг отсутствует# git будет предлагать коммиты, а ты отвечаешь:git bisect good # бага нетgit bisect bad # баг есть# Найдёт коммит, внёсший баг (бинарный поиск по истории)git bisect reset # выйти
Автоматический bisect:
git bisect start HEAD <good-commit>
git bisect run ./test.sh # скрипт возвращает 0 = good, 1 = bad
Worktree: несколько рабочих копий
# Создать отдельную рабочую копию для другой веткиgit worktree add ../myapp-hotfix hotfix/critical
cd ../myapp-hotfix
# ... работать, не трогая основную копию ...git worktree remove ../myapp-hotfix
Зачем: работать над hotfix-ом, не прерывая текущую задачу и не используя stash.
Partial clone и sparse checkout
# Для огромных репозиториев — скачать только нужную папку:git clone --filter=blob:none --sparse <url>
cd repo
git sparse-checkout set src/backend
Хуки (hooks)
Скрипты, запускающиеся автоматически на определённые события:
ls .git/hooks/ # доступные хуки# Популярные:# pre-commit — проверки перед коммитом (линтер, тесты)# commit-msg — валидация сообщения коммита# pre-push — проверки перед push
Для управления хуками удобно использовать pre-commit:
pip install pre-commit
pre-commit install
Соглашения по коммитам (Conventional Commits)
<type>(<scope>): <description>
feat(auth): add JWT refresh token rotation
fix(api): handle null response from payment provider
docs(readme): update installation instructions
refactor(db): extract connection pool configuration
test(auth): add integration tests for login flow
chore(deps): update Go to 1.22
git switch -c feature/my-work # создать ветку на текущем коммитеgit switch main
git reset --hard HEAD~1 # откатить main (изменения уже в feature-ветке)
Закоммитил секрет (.env, ключ):
# Если ещё не запушил:git reset --soft HEAD~1 # убрать коммит# убрать секрет из файлов, добавить в .gitignoregit commit
# Если запушил — секрет скомпрометирован. Ротируй ключи.# Удалить из истории:git filter-repo --path .env --invert-paths