Git

Git — распределённая система управления версиями, предназначенная для отслеживания изменений в исходном коде и данных. Git широко используется программистами в процессе совместной разработки программного обеспечения.

Основными целями при создании Git были высокая скорость работы, целостность данных и поддержка распределённых и нелинейных сценариев разработки с большим количеством параллельных веток. Как и большинство систем распределённого управления версиями, Git хранит полную локальную копию всего репозитория, включая историю изменений, что позволяет работать с проектом и отслеживать его историю без постоянного доступа к сети или центральному серверу. Git предоставляет средства для синхронизации изменений между репозиториями, в том числе на удалённых машинах. Для организации интеграции изменений часто пользуются центральным сервером, однако все репозитории равноправны.

Git распространяется как свободное и открытое программное обеспечение на условиях лицензии GPL-2.0-only.

Git был создан Линусом Торвальдсом для управления версиями в процессе разработки ядра Linux. Торговая марка «Git» зарегистрирована организацией Software Freedom Conservancy.

Сегодня Git является фактическим стандартом управления версиями: по данным за 2022 год, им пользуются почти 95 % профессиональных разработчиков, а сервисы для размещения Git-репозиториев, такие как GitHub, SourceForge, Bitbucket и GitLab, стали индустриальным стандартом.

Что важно знать
Git
Тип Система управления версиями
Автор Линус Торвальдс
Разработчики Хамино Джунио и др.
Написана на преимущественно C, а также сценарии на Shell, Perl, Tcl, Python
Операционные системы POSIX (включая Linux, macOS, Solaris, AIX), Windows
Языки интерфейса английский
Первый выпуск 7 апреля 2005
Последняя версия
Репозиторий github.com/git/git
Лицензия GPL-2.0-only
Сайт git-scm.com

История

Разработка Git началась Линусом Торвальдсом в апреле 2005 года после того, как свободная лицензия на проприетарную систему управления версиями BitKeeper, использовавшуюся для работы над ядром Linux с 2002 года, была отозвана. Это решение побудило также создание альтернатив — в частности, Mercurial. Торвальдс хотел получить распределённую систему с функционалом BitKeeper, однако существовавшие на тот момент свободные аналоги не удовлетворяли его требованиям по производительности и безопасности. Критериями стали: производительность — применение патча и обновление метаданных не более чем за 3 секунды (в отличие от 30 секунд у альтернатив), поддержка распределённой работы и устойчивость к повреждениям данных.

Разработка Git стартовала 3 апреля 2005 года; уже 6 апреля проект был анонсирован, а начиная с 7 апреля для поддержки ядра Linux стала применяться самособирающаяся версия системы. Первая слияние веток реализовано 18 апреля, а к 16 июня на Git уже осуществлялись полноценные релизы ядра Linux.

26 июля 2005 года Линус Торвальдс передал поддержку и развитие Git Джунио Хамино, одному из ключевых участников проекта, который выпустил версию 1.0 21 декабря 2005 года.

Название

Линус Торвальдс иронично прокомментировал выбор названия «git» (в британском английском сленге — «недотёпа», «придурок»): «Я эгоистичный ублюдок, называю все свои проекты в честь себя. Сначала — „Linux“, теперь — „git“». В man-странице система определяется как «тупой трекер содержимого». В файле README исходного кода отмечается:

"git" может значить всё что угодно, в зависимости от вашего настроения:

  • Случайная трёхбуквенная комбинация, не совпадающая с командами UNIX; возможная неправильная транслитерация «get».
  • Глупый, презренный, простой. Выберите любое значение из сленгового словаря.
  • «Global information tracker»: когда всё работает — ангелы поют, свет наполняет комнату.
  • «Goddamn idiotic truckload of sh*t»: когда всё ломается.

В исходных файлах Git система называется «the information manager from hell» (информационный менеджер из ада).

Характеристики

Архитектура и принципы работы

Дизайн Git основан на опыте Торвальдса по поддержке масштабных распределённых проектов (ядро Linux) и знании быстродействия файловых систем. Было реализовано:

Поддержка нелинейной разработки
Git облегчает быстрое ветвление и объединение, включает средства визуализации истории, а сами ветки представляют собой просто ссылки на коммиты.
Распределённая модель
каждый пользователь хранит локальную копию полной истории разработки; изменения между репозиториями импортируются в виде веток и могут объединяться.
Совместимость
поддерживается публикация репозиториев по HTTPS, HTTP, FTP и собственному протоколу Git, а также эмуляция сервера CVS для поддержки соответствующих клиентов и плагинов IDE. Конвертация репозиториев Subversion реализуема через git-svn.
Высокая производительность
Git оптимизирован для работы с большими проектами и может на порядки превосходить другие системы по скорости операций.
Криптографическая целостность
идентификатор версии-коммита зависит от истории изменений и реализован на основе SHA-1, так что искажение истории можно легко выявить.
Модульная структура
большинство команд реализовано как отдельные программы на C, обёрнутые в shell-скрипты; компоненты можно объединять в цепочки.
Расширяемость слияния
поддерживаются плагины стратегий слияния, а в случае невозможности автослияния пользователь получает требование разрешить конфликт вручную.
Сборка «мусора»
ненужные объекты, создаваемые при завершении операций, автоматически удаляются сборщиком мусора (git gc); также возможна ручная сборка.
Упаковка объектов
для экономии пространства объекты периодически сохраняются в pack-файлы с delta-компрессией и индексами, поддерживается контроль целостности через SHA-1, анализ целостности — командой git fsck.

Git оперирует снимками состояний (snapshot) каталогов, не отслеживая индивидуальных историй отдельных файлов.

Особенности и ограничения

  • Для просмотра истории изменений отдельного файла требуется обход истории всего проекта.
  • Переименования обнаруживаются по эвристике при просмотре истории, а не фиксируются явно, и требуют больше вычислений.

Cтратегии слияния

Git реализует ряд стратегий слияния веток<ref name="merge">:

  • resolve — классический трёхсторонний алгоритм;
  • recursive — вариант resolve по умолчанию при слиянии одной ветки (уменьшает количество конфликтов, поддерживает обнаружение переименований);
  • octopus — применяется при слиянии более двух веток.

Структуры данных

Основные структуры данных в Git — изменяемый индекс (stage/cache), кэширующий информацию о рабочем каталоге и будущем коммите, и неизменяемая база объектов.

В базе хранятся пять типов объектов:

  • blob — содержимое файла;
  • tree — эквивалент директории со списками файлов и ссылками на объекты;
  • commit — связывает tree-объекты в историю;
  • tag — контейнер метаданных, часто для подписи релизов;
  • packfile — сжатый пакет объектов для компактного хранения.

Каждый объект идентифицируется хешем SHA-1; имена и организация каталогов строятся на основе хеша. Объекты можно группировать в пакеты для экономии дискового пространства (используется delta-компрессия).

Для навигации по истории используются ссылки (refs): ветки (heads), HEAD (текущая активная ветка), теги (tags).

Команды

Основные команды Git для работы из командной строки:

  • git init — создать новый репозиторий;
  • git clone [URL] — клонировать внешний репозиторий;
  • git add [файл] — добавить файл в индекс (для фиксации изменений);
  • git commit -m "[комментарий]" — зафиксировать изменения в репозитории.

Для игнорирования некоторых файлов можно создать текстовый файл .gitignore, где указываются файлы и шаблоны, которые не должны отслеживаться.

Ссылки (referencies)

Git поддерживает различные типы ссылок (references); для их просмотра используется команда git show-ref. Например:

  • heads — локальные ветки,
  • remotes — ветки в удалённых репозиториях,
  • stash — временные сохранения,
  • meta — метаданные (например, в Gerrit),
  • tags — теги.

Реализации

Основная реализация Git (на C) изначально создавалась и поддерживалась под Linux, однако существует поддержка большинства популярных ОС (BSD-семейство, Solaris, macOS, Windows).

Первая портированная версия для Windows включала эмулирующую среду Linux, а текущие официальные сборки распространяются как 32- и 64-разрядные установщики на базе MSYS2.

Существуют альтернативные реализации:

  • JGit — чистый Java-библиотека для встраивания Git в Java-приложения (используется в Gerrit, EGit);
  • go-git — реализация Git на Go, используется, в том числе, для SQL-интерфейса и шифрования;
  • Dulwich — на Python, поддерживает CPython 3.6+ и PyPy;
  • libgit2 — библиотека на ANSI C без сторонних зависимостей, поддерживает различные платформы и языки (Ruby, Python, Haskell);
  • JS-Git — реализация части Git на JavaScript;
  • Game of Trees — open source-реализация Git для OpenBSD.

Git-сервер

Как распределённая система, Git может быть сервером «из коробки» благодаря встроенной команде git daemon, запускающей простой TCP-сервер по протоколу Git; репозитории можно клонировать и использовать как центральное хранилище. Для управления доступом/публикации можно использовать отдельные HTTP-серверы, оболочку ssh, интегрированные web-интерфейсы.

Свободные решения

  • Gerrit — сервер Git с поддержкой кода-ревью, доступа через ssh/OpenSSH/Jetty и интеграцией авторизации;
  • Phabricator — поддержка Git наряду с Mercurial и Subversion;
  • RhodeCode Community Edition — поддержка Git, Mercurial и Subversion;
  • Kallithea — сервер на Python с поддержкой Git/Mercurial;
  • gitolite, Gogs, Gitea, Forgejo — самописные или форки, реализованные на Go, с открытым кодом и MIT-лицензией.

Git как облачный сервис

Сервисов хостинга Git-репозиториев множество; наиболее популярны GitHub, SourceForge, Bitbucket и GitLab.

Графические интерфейсы

Графические клиенты Git предоставляют пользовательский интерфейс для упрощения работы с репозиториями. Они визуализируют историю, ветки, коммиты, различия файлов, позволяют выполнять типовые действия (стадирование, коммиты, управление ветками/объединением, разрешение конфликтов).

Официальный GUI реализован на Tcl/Tk, поддерживает создание и изменение коммитов, управление ветками и взаимодействие с удалёнными хранилищами. Существуют и сторонние решения с расширенным функционалом.

Использование GUI снижает порог вхождения и повышает эффективность работы с системой контроля версий.

Применение

По данным отчёта Eclipse Foundation за май 2014 года, Git стал самым широко используемым инструментом управления версиями исходных текстов (42,9 % опрошенных разработчиков — против 36,3 % в 2013, 32 % в 2012). Похожие показатели приведены в open source-аналитике Open Hub.

В ежегодных опросах Stack Overflow Git уверенно лидирует с долей до 93,9 % опрошенных (2022); аналогичные значения подтверждаются по опиcаниям вакансий IT-работы в Великобритании.

Применяемость различных систем управления версиями среди разработчиков (по Stack Overflow):

Название 2015 2017 2018 2022
Git 69,3 % 69,2 % 87,2 % 93,9 %
Subversion 36,9 % 9,1 % 16,1 % 5,2 %
TFVC 12,2 % 7,3 % 10,9 %
Mercurial 7,9 % 1,9 % 3,6 % 1,1 %
CVS 4,2 %
Perforce 3,3 %
VSS 0,6 %
IBM DevOps Code ClearCase 0,4 %
Zip file backups 2,0 % 7,9 %
Raw network sharing 1,7 % 7,9 %
Другое 5,8 % 3,0 %
Не используют 9,3 % 4,8 % 4,8 % 4,3 %

Расширения

К Git доступно множество расширений, в частности, Git LFS для работы с большими файлами, git-annex (распределённая синхронизация медиафайлов), git-flow (автоматизация ветвлений), git-machete (органайзер веток).

Корпорация Microsoft разработала Virtual File System for Git (VFS for Git) — расширение для поддержки масштабных репозиториев на Windows, позволяющее скачивать содержимое файлов только при обращении.

Конвенции

  • По умолчанию git init создаёт ветку master (во многих современных инструментах вместо неё применяется main).
  • Коммиты в общих репозиториях обычно не перезаписывают, а отменяют дополнительным коммитом с обратимыми изменениями.
  • Популярна модель работы git-flow с отдельными ветками: feature/* (разработка), develop (нестабильная), main (стабильная), hotfix (экстренные исправления).
  • Pull request/merge request — не встроенная функция Git, а возможность облачных сервисов; по сути это тикет на сервере для объединения веток с ручной модерацией.

Безопасность

Git не реализует механизмов контроля доступа, полагаясь на внешние инструменты.

В декабре 2014 года была выявлена уязвимость, позволяющая злоумышленнику выполнять произвольный код на Windows и macOS при загрузке и раскрытии особых директорий .git, что было исправлено в версии 2.2.1.

В сентябре 2015 года устранена критическая уязвимость (CVE-2015-7545), также связанная с возможностью удалённого исполнения кода при особых условиях клонирования.

Хотя SHA-1 использовался в первую очередь для контроля целостности, после атаки SHAttered в 2017 году Git внедрил модифицированный SHA-1 и разрабатывает переход на другие хеши.

Торговая марка

Слово «Git» зарегистрировано в качестве товарного знака организацией Software Freedom Conservancy в США (с 3 февраля 2015 года).

Примечания