Системы контроля версий и Git¶
На каком бы языке программирования вы ни работали — в команде, фрилансером или для себя — без системы контроля версий не обойтись. Эта статья — короткий обзор Git и его экосистемы.
Что такое контроль версий¶
Система контроля версий (СКВ, VCS — Version Control System) регистрирует изменения файлов так, чтобы в любой момент можно было:
- вернуться к предыдущей версии,
- сравнить две версии и понять, что изменилось,
- работать вместе с другими разработчиками без конфликтов,
- хранить полную историю проекта.
Типичный сценарий: выложили новую версию в продакшен, начали работать над новыми фичами — и вдруг обнаружили баг в старой. Нужно вернуться к рабочей версии, исправить и не потерять начатую работу. СКВ это делает естественно.
Без СКВ многие пытаются обойтись копированием каталогов (my_project_v1, my_project_v2_final, my_project_FINAL_FINAL). Минусы такого подхода:
- избыточность: дублируется весь код, а не только изменения;
- нет коллективной работы: двум людям невозможно править одновременно;
- нет истории: непонятно, что именно изменилось и зачем.
Виды СКВ¶
Локальные (исторический интерес)¶
Первые СКВ — например, RCS (1985) — хранили историю в локальной БД. Решали только проблему избыточности (через дельта-компрессию).
Централизованные (CVS, Subversion, Perforce)¶
Один центральный сервер хранит все версии, клиенты получают копии нужных. Долго были стандартом индустрии. Недостатки:
- сервер — единая точка отказа;
- нет работы оффлайн (всё через сервер);
- сложно ветвиться и сливать.
Распределённые (Git, Mercurial, Bazaar)¶
Каждый клиент имеет полную копию репозитория со всей историей. Сервер (если есть) — точка синхронизации, а не единый источник истины. Преимущества:
- работа оффлайн;
- быстрые локальные операции;
- любой клон может стать новым центральным репозиторием;
- мощное ветвление и слияние.
На сегодня Git — стандарт де-факто (~95% open-source проектов). В этой статье говорим только про Git.
Особенности Git¶
Почти все операции — локальные¶
Чтобы посмотреть историю, сделать коммит или сравнить версии, Git'у не нужен сервер. Это:
- очень быстро (история — в
.git/); - работает без интернета (в поезде, в самолёте);
- сетевые операции — только
push/pull/fetch.
Целостность данных¶
Каждый объект Git (файл, коммит, дерево) идентифицируется по SHA-1 (с переходом на SHA-256). Невозможно незаметно изменить файл — Git это заметит. Контрольные суммы — фундамент архитектуры Git.
Чаще всего данные только добавляются¶
Практически любая операция Git'а добавляет данные в репозиторий, а не удаляет. Это значит:
- отменить операцию обычно можно — данные ещё в
.git/; - ошибки восстанавливаются (через
reflog); - редкие «по-настоящему опасные» команды —
git reset --hard,git push --force,git clean -fd.
Три состояния файлов¶
Это ключевое для понимания Git'а. Файл может находиться в одном из трёх состояний:
| Состояние | Что значит |
|---|---|
| Modified (изменён) | поменялся, но не подготовлен к коммиту |
| Staged (подготовлен) | отмечен для следующего коммита |
| Committed (зафиксирован) | сохранён в локальной базе |
Стандартный workflow:
flowchart LR
A[Рабочий каталог] -->|git add| B[Индекс / staging]
B -->|git commit| C[Локальный репозиторий]
C -->|git push| D[Удалённый репозиторий]
D -->|git pull / fetch| C
Установка Git¶
macOS¶
Linux¶
Windows¶
Скачайте инсталлятор с gitforwindows.org. В комплекте — git, Git Bash (Unix-подобный shell), SSH-клиент и (опционально) графические инструменты.
После установки проверьте версию:
Первоначальная настройка¶
Git хранит настройки в трёх уровнях:
--system— для всех пользователей системы;--global— для текущего пользователя (хранятся в~/.gitconfig);- по умолчанию — для конкретного репозитория (
.git/config).
Имя и почта¶
Каждый коммит содержит автора. Установите имя и email до первого коммита:
Редактор по умолчанию¶
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim" # Vim
git config --global core.editor "nano" # Nano
Современные удобства¶
# Имя ветки по умолчанию
git config --global init.defaultBranch main
# Цветной вывод
git config --global color.ui auto
# Авто-rebase при pull (избегает мёрж-коммитов)
git config --global pull.rebase true
# Сохранять учётные данные на 1 час
git config --global credential.helper "cache --timeout=3600"
# На macOS — использовать Keychain
git config --global credential.helper osxkeychain
# Включить интеллектуальную обработку line endings
git config --global core.autocrlf input # macOS / Linux
git config --global core.autocrlf true # Windows
SSH-ключи для GitHub/GitLab¶
Аутентификация по паролю давно устарела. Используйте SSH:
# Создать ключ
ssh-keygen -t ed25519 -C "you@example.com"
# Запустить агент и добавить ключ
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Скопировать публичный ключ
cat ~/.ssh/id_ed25519.pub # вставьте на GitHub → Settings → SSH keys
Проверка:
Выбор хостинга¶
| Хостинг | Особенности |
|---|---|
| GitHub | Самый популярный, активная экосистема, бесплатные приватные репо. |
| GitLab | Cloud + self-hosted, встроенный CI/CD, есть бесплатная версия Community Edition. |
| Codeberg | Некоммерческий, fork Gitea, без слежки и без AI-обучения на коде. |
| Bitbucket | От Atlassian, тесно интегрирован с Jira. |
| Собственный | Gitea, GitLab CE, Forgejo — если нужны полный контроль и конфиденциальность. |
Базовые команды¶
Создание репозитория¶
Способ 1: с нуля
Способ 2: клонирование существующего
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # через SSH
git clone https://github.com/user/repo.git my-dir # в свой каталог
Статус и история¶
git status # что изменилось
git status -s # короткий формат
git log # история коммитов
git log --oneline # компактно
git log --graph --oneline --all # с ветками
git diff # неподготовленные изменения
git diff --staged # подготовленные изменения
git diff main..feature # между ветками
Добавление и коммит¶
git add file.txt # один файл
git add src/ # каталог
git add -p # интерактивно по кускам (patch mode)
git add . # всё в текущем каталоге (осторожно!)
git commit -m "feat: добавил поиск"
git commit # откроет редактор для многострочного сообщения
git commit -am "fix" # add + commit для отслеживаемых файлов
Игнорирование файлов¶
Создайте файл .gitignore в корне:
# Комментарий — эта строка игнорируется
# Python
__pycache__/
*.pyc
.venv/
.env
# Go
/bin/
*.exe
# IDE
.idea/
.vscode/
# Логи и временные
*.log
*.tmp
.DS_Store
# Скомпилированные
build/
dist/
# Отслеживать lib.a, даже если игнорируем все .a
*.a
!lib.a
Готовые шаблоны для языков и инструментов: github.com/github/gitignore.
Удаление и переименование¶
git rm file.txt # удалить и убрать из индекса
git rm --cached secrets.env # убрать из индекса, оставить на диске
git mv old.txt new.txt # переименовать
Отмена изменений¶
git restore file.txt # отменить неподготовленные изменения файла
git restore --staged file.txt # снять с индекса (не удалить изменения)
git restore --source=HEAD~1 file.txt # вернуть файл из предыдущего коммита
git revert <commit> # создать новый коммит, обращающий указанный
git reset HEAD~1 # «отменить» последний коммит (мягко — изменения остаются)
git reset --hard HEAD~1 # отменить ПОЛНОСТЬЮ (осторожно!)
Просмотр изменений¶
git show <commit> # детали коммита
git blame file.txt # кто и когда менял каждую строку
git log -p file.txt # история изменений конкретного файла
git log -S "string" # коммиты, добавившие/убравшие строку
Работа с удалёнными репозиториями¶
git remote -v # список удалённых
git remote add origin git@github.com:u/r.git # добавить
git remote remove origin # удалить
git remote rename origin upstream # переименовать
git fetch origin # забрать обновления, не сливая
git pull origin main # fetch + merge (или rebase)
git push origin main # отправить ветку
git push -u origin feature-x # отправить и установить tracking
git push --force-with-lease # безопасный force-push
--forcevs--force-with-lease:--forceперезаписывает удалённую ветку безусловно — можно случайно затереть чужую работу.--force-with-leaseпроверяет, что вы видели последние изменения и не перезатрёте чужой push. Всегда используйте именно--force-with-lease.
Ветвление¶
Главная сила Git'а — лёгкое и быстрое ветвление.
git branch # список локальных веток
git branch -a # с удалёнными
git branch feature-x # создать ветку
git switch feature-x # переключиться (современная команда)
git switch -c feature-y # создать + переключиться
git checkout feature-x # старая команда переключения
git merge feature-x # слить в текущую ветку
git merge --no-ff feature-x # с явным merge-коммитом
git rebase main # перебазировать текущую ветку на main
git branch -d feature-x # удалить слитую ветку
git branch -D feature-x # удалить принудительно (даже несли́тую)
git push origin --delete feature-x # удалить удалённую ветку
Популярные workflow¶
GitHub Flow — простой и популярный:
- Создаём ветку от
main. - Коммитим изменения.
- Открываем Pull Request.
- Получаем review, обсуждаем, исправляем.
- Сливаем в
main. - Удаляем ветку.
Git Flow (более сложный, для релизных циклов):
main— продакшен;develop— основная ветка разработки;feature/*,release/*,hotfix/*— короткоживущие ветки.
Для большинства проектов GitHub Flow проще и хватает.
Conventional Commits¶
Современная конвенция для сообщений коммитов:
Типы:
feat:— новая фича;fix:— исправление бага;docs:— изменения только в документации;style:— форматирование, без логики;refactor:— переделка без изменения поведения;test:— добавление/изменение тестов;chore:— рутинная работа (зависимости, конфиги);build:— изменения в сборке;ci:— CI/CD-конфиги.
Примеры:
feat(auth): добавить вход по Google
fix(api): исправить race condition в обработчике webhook
docs(readme): обновить инструкцию запуска
refactor: вынести вычисление цены в отдельный модуль
BREAKING CHANGE: переименовали /api/users в /api/v2/users
Зачем это нужно:
- читаемая история;
- автоматическая генерация changelog;
- автоматическое определение версии (по
feat:минорная, поfix:патч, поBREAKING CHANGEмажорная).
Полезные команды¶
Stash — отложить изменения¶
git stash # отложить все незакоммиченные изменения
git stash list # список «отложенных»
git stash pop # вернуть последние и удалить из stash
git stash apply # вернуть, но оставить в stash
git stash drop # удалить последний
git stash push -m "wip auth" # с описанием
Сценарий: вы работаете над фичей, но срочно нужно исправить баг в main. git stash → переключаетесь в main → правите баг → возвращаетесь → git stash pop.
Cherry-pick — взять конкретный коммит¶
Reflog — спасение жизни¶
git reflog # история всех HEAD-перемещений
git reset --hard HEAD@{3} # вернуться к тому, что было «3 шага назад»
Reflog хранит локально все перемещения HEAD в течение ~90 дней. Если случайно сделали git reset --hard и потеряли коммиты — почти наверняка их можно вернуть через reflog.
Bisect — двоичный поиск регрессии¶
git bisect start
git bisect bad # текущий коммит — сломан
git bisect good v1.0 # v1.0 — работала
# Git переключает на середину истории; вы тестируете и говорите good/bad
git bisect good # или git bisect bad
# ... повторяете, пока Git не найдёт виновный коммит
git bisect reset # выйти из режима bisect
Незаменим для поиска регрессий в большой истории.
Чего НЕ нужно делать¶
- ⛔ Коммитить секреты (пароли, токены, приватные ключи). Если случайно — токен скомпрометирован, история всё равно содержит его навсегда. Используйте
git secrets,gitleaksили pre-commit хуки. - ⛔
git push --forceв общую ветку (main,develop). Используйте--force-with-leaseи только для собственных feature-веток. - ⛔ Хранить большие бинарные файлы в Git. Используйте Git LFS, S3 или другое внешнее хранилище.
- ⛔ Очень большие коммиты «через раз». Лучше много маленьких атомарных коммитов.
- ⛔
git pull --rebaseв общей ветке после push. Если уже отправили — теперь только мёрж.
Современные дополнения¶
- GitHub CLI (
gh) — работать с PR, issues, актами и релизами из терминала:gh pr create,gh issue list,gh repo clone. - lazygit — TUI для Git с горячими клавишами для всех операций.
- tig — просмотрщик истории в терминале.
- delta — красивый цветной diff поверх Git.
- pre-commit — фреймворк для запуска хуков перед коммитом (линтер, форматтер, проверка секретов).
- husky — то же для проектов на Node.js/TypeScript.
Где учиться дальше¶
- Pro Git — официальная книга, переведена на русский.
- Learn Git Branching — визуальный интерактивный туториал.
- GitHub Skills — официальные курсы.
- Oh Shit, Git!?! — как откатить типичные косяки.
Контрольные вопросы¶
- В чём принципиальное отличие распределённой СКВ от централизованной?
- Какие три состояния файла бывают в Git и через какие команды они переходят?
- Чем
git pullотличается отgit fetch? - Что такое
--force-with-leaseи почему он безопаснее обычного--force? - Когда применять
git merge, а когдаgit rebase? - Что хранит файл
.gitignoreи какие шаблоны он поддерживает? - Что такое Conventional Commits и какие плюсы они дают?
- Как восстановить случайно удалённый коммит?
- Зачем нужен
git bisect? - Какие данные никогда не должны попадать в Git-репозиторий?