Git Workflow

Если вы работаете в IT, то используете Git каждый день. Но для большинства разработчиков вся работа с ним сводится к заученной тройке команд: add, commit и push. Если что-то идет не так — проще удалить папку с проектом и склонировать его заново.

В этой статье мы уйдем от слепого копирования команд. Разберем, как Git появился на свет из-за громкого скандала с правами на софт, чем его архитектура принципиально отличается от старых систем вроде SVN, подкрепим все ссылками на официальные источники и настроим всё с нуля.


1. История: Как скандал с BitKeeper заставил Линуса написать Git

До 2002 года ядро Linux разрабатывалось «на коленке»: разработчики со всего мира присылали Линусу Торвальдсу текстовые патчи и архивные файлы по электронной почте, а он вручную накладывал их на исходный код.

Когда проект разросся до сотен мейнтейнеров, вручную следить за кодом стало невозможно. В 2002 году команда Linux приняла решение использовать BitKeeper — коммерческую распределенную систему контроля версий, компания-разработчик которой (BitMover) предоставила бесплатные лицензии сообществу Open Source (LWN: The kernel and BitKeeper part ways).

Партнерство продержалось 3 года и закончилось скандалом в апреле 2005 года:

  1. Эндрю Триджелл (создатель Samba) решил разобраться, как устроена клиентская часть BitKeeper, чтобы написать открытый инструмент для чтения метаданных (ZNet: Tridgell speaks out in BitKeeper war).
  2. Ларри МакВой (глава BitMover) обвинил сообщество в реверс-инжиниринге и заблокировал бесплатный доступ к BitKeeper для ведущих разработчиков ядра, включая Торвальдса.

Разработка ядра Linux оказалась заблокирована. Линус закрылся дома и за пару недель создал собственный инструмент на языке C. Первое официальное анонсирующее письмо о выходе Git было отправлено им в почтовую рассылку Linux Kernel Mailing List 11 апреля 2005 года.

Откуда такое название?
В британском сленге слово «git» означает «неприятный, занудный тип». На своей знаменитой лекции в Google в 2007 году Линус с иронией заметил: «Я наглый эгоист, поэтому называю проекты в честь себя: сначала Linux, теперь Git».


2. Архитектура: Почему Git — это не SVN

Главное отличие Git от классических систем (CVS, Subversion/SVN) заключается в подходе к хранению данных и топологии сети.

Централизованные VCS против Распределенных (DVCS)

В SVN есть один центральный сервер. Если вы едете в поезде без интернета — вы не можете сделать коммит, посмотреть историю изменений за прошлый месяц или создать новую ветку.

Централизованная (SVN):   [Разработчик] <---> [Центральный Сервер] <---> [Разработчик]
Распределенная (Git):     [Локальный репо] <---> [GitHub / GitLab] <---> [Локальный репо]

В Git каждая локальная копия репозитория на вашем компьютере содержит абсолютную и полную историю проекта со всеми ветками и тегами (Git Documentation: Pro Git Book, Глава 1.1).

Снимки (Snapshots), а не Разницы (Deltas)

  • SVN / CVS хранят базовый файл и бесконечный список дельт (разниц между версиями A $\to$ B $\to$ C). Чтобы восстановить файл из 100-го коммита, системе нужно последовательно применить 100 заплаток.
  • Git при каждом коммите делает слепок (snapshot) всего дерева файлов. Если файл не менялся в данном коммите, Git не дублирует его, а создает жесткую ссылку на ранее сохраненный объект.

Хеширование и переход с SHA-1 на SHA-256

Каждый объект в Git (файл, каталог, коммит) именуется по его криптографическому хешу. Долгое время использовался алгоритм SHA-1. Однако после того как исследовательская группа Google продемонстрировала практическую коллизию SHA-1 (атака SHAttered в 2017 году), сообщество разработало план миграции.

Сегодня в Git интегрирована поддержка SHA-256 для гарантированной защиты истории от подмены данных (Официальная документация: Git Hash Function Transition).


3. Золотые правила и инженерные практики

Работа с Git требует дисциплины. Вот правила, за соблюдение которых коллеги на код-ревью скажут вам спасибо:

1. Атомарность коммитов (Atomic Commits)

Один коммит должен закрывать ровно одну логическую задачу. Не надо в один коммит помещать переделку дизайна шапки, исправление бага в авторизации и обновление библиотек. Если баг-фикс вызовет регрессию, его можно будет легко отменить командой git revert, не затрагивая остальные правки.

2. Читаемые сообщения и Conventional Commits

Забудьте про коммиты fix, asdf, work done. Используйте спецификацию Conventional Commits:

  • feat(auth): add OAuth2 authorization via Google
  • fix(cart): resolve price calculation bug on checkout
  • docs(readme): add docker setup instructions

3. Никогда не отправляйте секреты в репозиторий

Пароли к БД, приватные SSH-ключи и API-токены должны жить в .env файлах.

  • Файл .gitignore создается до первого коммита.
  • Помните: если вы закоммитили файл .env, а следующим коммитом добавили его в .gitignore и удалили, токен остался в истории Git навечно. Удалять его придется специальными утилитами вроде git-filter-repo или сервисами вроде GitHub Secret Scanning.

4. Используйте изолированные ветки

Создавайте ветки под конкретные задачи (feature/cart-page, hotfix/login-crash) и сливайте их в основную ветку (main) через Pull/Merge Requests.


4. Quick Start: Базовая настройка и старт с нуля

Шаг 1. Глобальная конфигурация

Сразу после установки Git необходимо представиться системе (эти данные подставляются в каждый ваш коммит) и задать удобные умолчания:

# Имя и Email автора
git config --global user.name "Ваше Имя"
git config --global user.email "yourmail@example.com"

# Имя дефолтной ветки (современный стандарт — main)
git config --global init.defaultBranch main

# Удобный текстовый редактор для коммитов (nano, vim, code)
git config --global core.editor "nano"

# Проверить список всех настроек
git config --list

Шаг 2. Рабочий цикл (Workflow)

# 1. Создать новую папку и инициализировать репозиторий
mkdir my-app && cd my-app
git init

# 2. Проверить текущий статус файлов
git status

# 3. Добавить изменения в индекс (Staging Area)
git add index.html # Добавить один файл
git add .          # Добавить все файлы в текущей директории

# 4. Зафиксировать изменения с понятным комментарием
git commit -m "feat: initial project structure"

# 5. Посмотреть историю коммитов в виде компактного графа
git log --oneline --graph --all

Шаг 3. Безопасная работа с ветками

В современных версиях Git вместо старой универсальной команды git checkout используются более специализированные команды git switch и git restore.

# Создать новую ветку и сразу перейти на нее
git switch -c feature/add-header

# Вернуться обратно на главную ветку
git switch main

# Слить ветку фичи в текущую ветку
git merge feature/add-header

# Удалить отработанную ветку
git branch -d feature/add-header

5. Подводные камни, грабли и редкие факты

  • Опасность git push --force: Флаг -f жестко перезаписывает историю на удаленном сервере. Если ваш коллега успел отправить туда свой код, вы его затрете без возможности быстрого восстановления. Используйте безопасный аналог: git push --force-with-lease.
  • Большие бинарные файлы: Git очень плохо справляется с хранением видео, архивов и весомых бинарников. Для них разработан специальный плагин Git LFS (Large File Storage), который хранит в репозитории только текстовые указатели на файлы (Официальный сайт Git LFS).
  • Как спасти случайно удаленный коммит: Если вы сделали git reset --hard или удалили ветку с нужным кодом, коммиты не стираются из файловой системы мгновенно. Найдите хеш потерянного коммита с помощью лога всех внутренних операций:
    git reflog
    После чего восстановите его командой git checkout <хеш_коммита>.

6. Официальные источники и полезные материалы