Система контроля версий: что это, какие бывают и как начать с Git

Система контроля версий: что это, какие бывают и как начать с Git Полезное

Система контроля версий (VCS, version control system) — программа, которая хранит историю изменений файлов проекта: что изменилось, кто и когда это сделал. Она позволяет вернуться к прежнему состоянию и объединять работу нескольких людей без ручного копирования папок.

Ниже — виды систем, сравнение 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 осваивать нужно в основном команды и работу с центральным сервером.

OTUS Журнал