Представьте: 1982 год, где-то в Университете Пердью Уолтер Тичи пытается контролировать версии своего кода с помощью перфокарт и молитв. Перенесёмся в сегодняшний день, когда я могу случайно выполнить команду rm -rf для своего проекта и маниакально смеяться, пока Git воскрешает его. Давайте разберёмся, как мы к этому пришли — с практическими примерами, папиными шутками и по крайней мере одной завуалированной отсылкой к «Звёздному пути».

Эра RCS: когда код хранился в Форт-Ноксе

Система контроля версий (RCS) была оригинальной системой контроля версий, которая обращалась с файлами как с редкими библиотечными книгами — одновременно их мог взять только один человек. Вот как вы могли бы использовать её сегодня (если вам нравится цифровая археология):

# Создание вашего первого цифрового каменного скрипта
$ ci -u important_script.sh
RCS/important_script.sh,v  <--  important_script.sh
initial revision: 1.1

Рабочий процесс RCS выглядел так:

  1. Блокировка файла, будто это последний кусок пиццы.
  2. Редактирование под пристальными взглядами коллег.
  3. Возврат с сообщением в журнале вроде «Исправлена ошибка (пожалуйста, работает)». Ключевые инновации:
  • Обратные дельты (хранение изменений в обратном порядке, как инструкции IKEA).
  • Простые инструменты CLI (ci = регистрация, co = проверка).
  • Управление версиями на уровне файлов (идеально подходит для одного конфигурационного файла, который вы постоянно ломаете).
graph LR A[Файл v1.0] -->|ci| B["Файл, v (дельта-пирамида)"] B -->|co| C[Файл v1.1] C -->|ci| B

Но у RCS были свои особенности:

  • Отсутствие атомарных коммитов (представьте себе сохранение каждой буквы в слове отдельно).
  • Ад блокировок («Дейв, я знаю, что ты в отпуске — освободи конфигурацию!»).
  • Ветвление? Больше похоже на веточки. Разработчики избегали их, как ошибок шаблонов C++.

CVS: первый командный игрок

Когда в 1986 году появилась CVS (система одновременных версий), это было всё равно что перейти от раций к Slack. Наконец-то несколько разработчиков могли ахнуть и работать одновременно! Практическая настройка CVS:

$ cvs import -m "Initial commit" project-name vendor-tag release-tag
$ cvs checkout project-name

Таблица инноваций CVS:

ФункцияRCSCVS
КоллаборацияБлокировка одного файлаМножество редакторов
Поддержка сетиЛокальная файловая системаКлиент-сервер
Отслеживание историиДля каждого файлаДля всего проекта
Разрешение конфликтов«Подождите своей очереди!»«Слияние с осторожностью»

Но вскоре разработчики обнаружили тёмную сторону CVS:

  • Отсутствие атомарных коммитов (потеря половины изменений было обрядом посвящения).
  • Ориентация на файлы, а не на общее видение проекта.
  • Пометка релизов была похожа на ловлю кошек Шрёдингера.

Вмешательство Subversion

Когда в 2000 году появился SVN, это было похоже на то, что CVS пошла в школу обаяния. Атомарные коммиты! Контроль версий каталогов! Лучшее ветвление (хотя всё ещё неуклюжее). Давайте отправимся в путешествие во времени:

$ svn checkout http://svn.example.com/repos/trunk
$ svn commit -m "Исправлено исключение нулевого указателя (lol jk)"

Забавные трюки SVN:

  • Версионированные каталоги (наконец-то отслеживание перемещений!).
  • Более чистое слияние (всё ещё требовался доктор наук по разрешению конфликтов).
  • Поддержка HTTP (WebDAV был REST API до того, как это стало круто). Но у SVN был экзистенциальный кризис — он был централизован, как CVS, в мире, жаждущем распределённых систем. Отправка в репозиторий была похожа на отправку открытки богам мейнфреймов.

Git: Распределённый повелитель времени

Затем в 2005 году Линус Торвальдс создал Git, якобы между завтраком и обедом. Git рассматривал каждый клон как полноценный репозиторий — словно давая каждому разработчику TARDIS. Современное волшебство Git:

# Инициализация репозитория
$ git init
$ git add .
$ git commit -m "Начальная фиксация (пожалуйста, не нарушайте)"
# Создать ветку функций
$ git checkout -b feature/rewrite-everything
# Путешествия во времени стали проще
$ git reflog  # "О верно, вот где я оставил свою вменяемость"
graph TD A[Локальный репозиторий] -->|push| B[Удаленный репозиторий] B -->|clone/pull| C[Dev 1] B -->|clone/pull| D[Dev 2] C -->|push| B D -->|push| B

Убойные функции Git:

  • Всё распределено (код, история, обвинения).
  • Молниеносные операции (слияние быстрее, чем у белки с кофеином).
  • Простое ветвление (git-flow, GitHub Flow, 42-часовая пятничная работа). Совет: хотите почувствовать себя старым? Первый коммит Git (b9652005) теперь достаточно взрослый, чтобы пить алкоголь в США.

Практическая эволюция: от RCS до Git за 4 шага

Давайте совершим путешествие во времени с помощью практических примеров: 1. Блокировка в стиле RCS в Git (на самом деле этого делать не стоит)

# Заблокировать config.ini, как в 1985 году
$ git update-index --assume-unchanged config.ini

2. Центральный рабочий процесс в стиле CVS

# Единое центральное хранилище, все разработчики отправляют изменения в основной
$ git config --global pull.rebase true
$ git push origin main

3. Контроль версий каталогов в стиле SVN

# Отслеживать пустые каталоги с помощью .gitkeep
$ mkdir -p logs && touch logs/.gitkeep

4. Современные мощные приемы работы с Git

# Интерактивное перебазирование (редактирование истории)
$ git rebase -i HEAD~3
# Поиск ошибок bisect to find
$ git bisect start
$ git bisect bad
$ git bisect good v1.0

Почему эта история важна сегодня

Понимание эволюции систем контроля версий помогает устранять современные проблемы:

  • Синтаксис .gitignore? Произошёл от файлов ignore в RCS.
  • Стадии изменений Git? Духовный преемник CVS «обновление перед фиксацией».
  • Конфликты слияния всё ещё неприятны, но теперь у нас есть лучшие инструменты для поиска виноватых. В следующий раз, когда будете выполнять git push, помните: где-то файл RCS плачет от радости. Мы перешли от управления версиями отдельных файлов к волшебному синхронному обновлению кодовых баз планетарного масштаба. Неплохо для нескольких десятилетий работы. А теперь извините меня, мне нужно зафиксировать эту статью, прежде чем мой редактор отправит поисковую группу.