Система контроля версий (VCS, version control system) — программа, которая хранит историю изменений файлов проекта: что изменилось, кто и когда это сделал. Она позволяет вернуться к прежнему состоянию и объединять работу нескольких людей без ручного копирования папок.
Содержание
- Мини-словарь: четыре слова, которые путают
- Зачем нужен контроль версий
- Виды систем контроля версий
- Git, Subversion и Mercurial: что выбрать
- Как Git хранит изменения: три области
- Базовый цикл Git: полный пример
- Конфликт слияния: ошибка и исправление
- Как вернуться к прежней версии
- Секреты и .gitignore
- Если не получилось
- Выводы
- Где применяется / связь с практикой
- FAQ
Ниже — виды систем, сравнение Git, SVN и Mercurial и базовый цикл Git от первого коммита до конфликта слияния. Примеры проверены на Git 2.43 (Linux) и 2.50 (macOS) 23 сентября 2026 года.
Мини-словарь: четыре слова, которые путают
- Репозиторий — хранилище проекта вместе с историей. В Git это скрытая папка
.gitвнутри каталога проекта. - Коммит — зафиксированное состояние проекта с автором, датой и сообщением. Из коммитов складывается история.
- Ветка — именованная линия разработки, указатель на последний коммит этой линии.
- Слияние (merge) — объединение изменений из двух веток в одну.
И еще пара: Git — программа контроля версий, а GitHub и GitLab — сервисы для удаленных копий Git-репозиториев и обсуждения изменений. Git работает и без них.
Зачем нужен контроль версий
Без VCS история проекта живет в именах файлов вроде report_final_2.docx, а работа вдвоем над одним файлом заканчивается перезаписью чужих правок. VCS показывает построчную разницу между версиями, позволяет отменить неудачное изменение, вести параллельные ветки и хранит автора и причину каждой правки.
Граница: VCS не заменяет резервное копирование. Репозиторий на единственном диске пропадет вместе с диском, поэтому историю держат еще и в удаленной копии.
Виды систем контроля версий
| Вид | Где хранится история | Коммит без связи с сервером | Примеры |
|---|---|---|---|
| Локальные | На одном компьютере | Да, но общей работы нет | RCS |
| Централизованные | На центральном сервере | Нет, коммит сразу уходит на сервер | Subversion (SVN), Perforce |
| Распределенные | У каждого участника полная копия | Да, обмен с сервером — отдельный шаг | Git, Mercurial |
Централизованной системе нужен доступ к серверу, не обязательно к интернету: сервер может стоять в локальной сети. В распределенной коммиты и ветки работают офлайн, сеть нужна для обмена (git push, git pull). Оговорка: git clone --depth 1 дает неполную копию без старой истории, так делают в CI ради скорости.
Git, Subversion и Mercurial: что выбрать
| Критерий | Git | Subversion | Mercurial |
|---|---|---|---|
| Модель | Распределенная | Централизованная | Распределенная |
| Появился | 2005 | 2000 (CollabNet, в Apache с 2010) | 2005 |
| Ветки | Дешевые, основа работы | Копии каталогов на сервере | Есть, плюс именованные ветки и закладки |
| Блокировка файлов | Через расширение Git LFS | Встроенная (svn lock) |
Через расширения |
Как выбирать. Новый проект или первое знакомство — Git: на нем работают GitHub, GitLab, CI/CD и большинство команд. SVN остается там, где он уже внедрен, и там, где много больших бинарных файлов: блокировка не дает двоим одновременно править одну текстуру. Mercurial берут, если он уже используется в проекте.
Сам Git хранит любые файлы, но не умеет сливать изображения или видео, а каждая версия большого файла раздувает историю. Расширение Git LFS (не Git по умолчанию) заменяет такие файлы указателями, а содержимое держит на отдельном сервере.
Как Git хранит изменения: три области
Файл в Git проходит три места: рабочий каталог (файлы, которые вы редактируете) -> индекс, или staging (то, что войдет в следующий коммит) -> коммит (зафиксированное состояние). Команда git add переносит изменение в индекс, git commit фиксирует индекс.
Упрощенно коммит — снимок всего проекта. Точнее: коммит ссылается на полное дерево файлов, но неизмененные файлы не копируются, а переиспользуются из прошлых коммитов.
Базовый цикл Git: полный пример
Скрипт создает репозиторий, делает коммит, ведет изменение в ветке и вливает его в main. Запуск — в bash (Linux, macOS, Git Bash на Windows) в пустой папке.
mkdir hello && cd hello
git init -b main
git config user.name "Anna"
git config user.email "anna@example.com"
echo "Привет" > greeting.txt
git status --short
git add greeting.txt
git status --short
git commit -m "Первая версия приветствия"
git switch -c feature
echo "Пока" >> greeting.txt
git commit -am "Добавлено прощание"
git switch main
git merge feature
git log --oneline --graph --format="%s"
cat greeting.txt
Главное в выводе (хеши коммитов у вас будут другими):
?? greeting.txt
A greeting.txt
[main (root-commit) 1e5a239] Первая версия приветствия
Switched to a new branch 'feature'
[feature 3639034] Добавлено прощание
Switched to branch 'main'
Updating 1e5a239..3639034
Fast-forward
* Добавлено прощание
* Первая версия приветствия
Привет
Пока
Разбор по шагам:
| Команда | Что делает |
|---|---|
git init -b main |
Создает репозиторий с веткой main. Без -b в Git 2.x ветка называется master, если не задана настройка init.defaultBranch. В Git 3.0 (на сентябрь 2026 не вышел, даты нет) новые репозитории получат main по умолчанию |
git config user.name/email |
Задает автора коммитов в этом репозитории (с --global — для всех) |
git status --short |
?? — файл не отслеживается, A — добавлен в индекс |
git switch -c feature |
Создает ветку и переходит на нее |
git commit -am |
Добавляет в индекс измененные отслеживаемые файлы и коммитит (новые файлы так не попадут) |
git merge feature |
Вливает ветку. Fast-forward — в main не было своих коммитов, указатель просто сдвинулся вперед |
Конфликт слияния: ошибка и исправление
Конфликт возникает, когда две ветки по-разному изменили одну и ту же строку. Продолжим тот же репозиторий:
git switch -c polite
printf 'Здравствуйте\nПока\n' > greeting.txt
git commit -qam "Вежливое приветствие"
git switch main
printf 'Привет всем\nПока\n' > greeting.txt
git commit -qam "Приветствие для всех"
git merge polite
cat greeting.txt
Фактический результат:
CONFLICT (content): Merge conflict in greeting.txt
Automatic merge failed; fix conflicts and then commit the result.
<<<<<<< HEAD
Привет всем
=======
Здравствуйте
>>>>>>> polite
Пока
Выше ======= версия текущей ветки, ниже — вливаемой. Исправление — оставить нужный текст без маркеров и закоммитить:
printf 'Здравствуйте, все\nПока\n' > greeting.txt
git add greeting.txt
git commit -m "Слияние веток main и polite"
git log --oneline --graph --format="%s"
* Слияние веток main и polite
|\
| * Вежливое приветствие
* | Приветствие для всех
|/
* Добавлено прощание
* Первая версия приветствия
Как вернуться к прежней версии
| Задача | Команда | Граница |
|---|---|---|
| Отменить незакоммиченные правки файла | git restore greeting.txt |
Правки пропадут без возможности вернуть |
| Убрать файл из индекса, сохранив правки | git restore --staged greeting.txt |
Файл остается в рабочем каталоге |
| Отменить уже сделанный коммит | git revert HEAD |
Создает новый коммит-отмену, история не переписывается |
Для коммитов, уже отправленных в общий репозиторий, безопаснее git revert. Команда git reset переписывает историю и годится только для локальных коммитов, которые еще никто не забрал.
Секреты и .gitignore
Пароли, токены и файлы .env не должны попадать в репозиторий. Список исключений пишут в .gitignore до первого коммита:
echo "API_KEY=secret123" > .env
printf '.env\n' > .gitignore
git status --short
git check-ignore -v .env
?? .gitignore
.gitignore:1:.env .env
check-ignore подтверждает, какое правило скрыло .env. Если секрет уже закоммичен и отправлен, удаление файла новым коммитом не помогает: он остается в истории и в чужих копиях. Ключ нужно отозвать и выпустить новый, чистка истории — только дополнительная мера.
Если не получилось
| Симптом | Причина | Что сделать |
|---|---|---|
Author identity unknown |
Не задан автор коммитов | git config --global user.name и user.email |
fatal: not a git repository |
Команда запущена вне папки репозитория | Перейти в папку проекта или выполнить git init |
nothing added to commit but untracked files present |
Файл не добавлен в индекс | git add <файл> перед git commit |
fatal: pathspec 'grreting.txt' did not match any files |
Опечатка в имени или неверный путь | Проверить имя через git status |
CONFLICT (content) |
Две ветки изменили одну строку | Разрешить маркеры, git add, git commit |
Дальше: удаленный репозиторий на GitHub или GitLab, git push и git pull, затем pull request (в GitLab — merge request) с ревью. Цель — свой репозиторий с осмысленной историей, влитой веткой и разрешенным конфликтом. Подробно о фиксации изменений, правке сообщения и составе коммита — в статье git commit: как сделать коммит в Git.
Выводы
- Система контроля версий хранит историю изменений, дает откатиться и объединять работу нескольких людей; резервное копирование она не заменяет.
- Централизованным (SVN) для коммита нужен сервер, распределенные (Git, Mercurial) держат полную историю у каждого участника и работают офлайн.
- Для нового проекта обычно выбирают Git; SVN остается там, где он внедрен или нужна блокировка больших бинарных файлов.
- Базовый цикл Git:
init->add->commit->switch -c->merge; конфликт решается правкой файла,addиcommit. - Отменять опубликованные коммиты безопаснее через
git revert, а секреты держать в.gitignoreс первого коммита.
Где применяется / связь с практикой
Освойте тему на практике
Из Git-репозитория запускаются сборки, тесты и выкладка, а в подходе GitOps в нем описывают и состояние инфраструктуры: ветки и слияния становятся частью конвейера поставки. Связку Git, CI/CD, контейнеров и автоматизации системно разбирают на курсе «DevOps практики и инструменты».
Освойте тему на практике
Попробовать формат и задать вопросы преподавателям можно на бесплатных открытых уроках Otus.
FAQ
Можно ли хранить в Git не код, а документы?
Да, но построчное сравнение и слияние работают для текстовых форматов (Markdown, CSV, конфиги). Версии .docx и изображений Git сохранит, но автоматически слить правки не сможет.
Delta Lake — это аналог Git?
Нет. Delta Lake — формат таблиц для озер данных с транзакциями и доступом к прошлым версиям таблицы, а не система контроля версий исходного кода.
Стоит ли изучать SVN в 2026 году?
Отдельно — только если он используется на проекте, куда вы идете. Базовые понятия (коммит, ветка, слияние, конфликт) переносятся, поэтому при переходе с Git на SVN осваивать нужно в основном команды и работу с центральным сервером.



