Git
| Тип | распределённая система контроля версий |
|---|---|
| Автор | Линус Торвальдс |
| Первый выпуск | апрель 2005 |
| Сопровождающий | Дзюнио Хамано (с июля 2005) |
| Языки | C, Shell, Perl |
| Лицензия | GNU GPL v2 |
| Хеш-функция объектов | SHA-1 (поддерживается SHA-256) |
| Сайт | git-scm.com |
Git — распределённая система контроля версий: программа, которая хранит историю изменений файлов проекта, позволяет вернуться к любой прошлой версии, вести параллельные линии разработки и объединять работу многих людей. «Распределённая» означает, что у каждого участника есть полная копия репозитория со всей историей, и большинство операций выполняется локально, без сервера.
Git используют подавляющее большинство разработчиков; на нём построены платформы GitHub и GitLab, процессы code review и CI/CD. Вне программирования Git применяют для документации, конфигураций (Infrastructure as Code) и даже книг.
История
С 2002 года ядро Linux разрабатывалось в коммерческой системе BitKeeper, которую авторы предоставляли сообществу бесплатно. В 2005 году бесплатную лицензию отозвали, и Линус Торвальдс за несколько дней написал собственную систему. Требования были чёткими: скорость, простая модель, поддержка тысяч параллельных веток, полная распределённость и способность работать с проектом размера ядра.[2] Первая версия появилась 7 апреля 2005 года, а уже в июле сопровождение перешло к Дзюнио Хамано, который ведёт проект до сих пор.
Название Торвальдс объяснял шутливо: git на британском сленге — «вредный тип», а он «называет все проекты в свою честь». Популярность Git резко выросла с запуском GitHub в 2008 году; к середине 2010-х он вытеснил Subversion, Mercurial и другие системы.
Модель данных
Git хранит не разницу между версиями, а снимки проекта. Все данные — объекты четырёх типов, адресуемые по хешу содержимого:[3]
| Объект | Что хранит |
|---|---|
| blob | содержимое файла |
| tree | каталог: имена файлов и ссылки на blob и другие tree |
| commit | ссылка на tree (снимок), родительские коммиты, автор, дата, сообщение |
| tag | именованная ссылка на коммит с подписью и описанием |
Одинаковые файлы хранятся один раз, а любое изменение в истории меняет хеши всех последующих коммитов — поэтому историю нельзя незаметно подделать. Исторически Git использует SHA-1; после демонстрации практической коллизии SHA-1 в 2017 году в Git добавлены защита от известных атак и поддержка SHA-256 для новых репозиториев.[4]
Ветки — это просто подвижные указатели на коммиты, поэтому создание ветки мгновенно; подробнее — в статье Ветвление в Git.
Три области
Файл в рабочем каталоге проходит через три состояния:
- Рабочий каталог (working tree) — файлы, которые вы редактируете.
- Индекс (staging area) — подготовленные к коммиту изменения;
git addпереносит их сюда. - Репозиторий (
.git) — зафиксированная история;git commitсоздаёт новый снимок из индекса.
Индекс позволяет собрать в один коммит только часть изменений — например, отделить исправление ошибки от попутного рефакторинга (git add -p).
Основные команды
git init # новый репозиторий
git clone git@github.com:user/repo.git
git status # что изменено
git add file.py # в индекс
git commit -m "Добавить проверку email"
git log --oneline --graph # история
git diff # изменения, ещё не в индексе
git switch -c feature/login # новая ветка
git merge feature/login # слить ветку
git pull # забрать изменения с сервера (fetch + merge/rebase)
git push origin feature/login # отправить ветку на сервер
git restore file.py # отменить локальные правки файла
git revert a1b2c3d # новый коммит, отменяющий старый
Подробное описание каждой команды есть в справочнике Git, а лучшее введение — бесплатная книга «Pro Git».[6][1]
Удалённые репозитории
Удалённый репозиторий (remote) — копия на сервере, обычно с именем origin. Git передаёт данные по SSH или HTTPS. Команда fetch скачивает новые коммиты, не трогая ваши ветки, pull дополнительно объединяет их с текущей веткой, push отправляет локальные коммиты. Поскольку у всех полные копии, потеря сервера не означает потерю истории.
Хорошие практики
- Небольшие осмысленные коммиты с сообщением в повелительном наклонении: что и зачем изменено.
- Файл
.gitignoreдля сборочных артефактов,.venv,node_modules, логов. - Никогда не коммитить секреты: ключ, попавший в историю, остаётся в ней и после удаления файла — его нужно отзывать.
- Не переписывать (
rebase,push --force) историю веток, которыми пользуются другие; про выбор между слиянием и перебазированием — Merge и rebase. - Версии релизов отмечать тегами по правилам семантического версионирования, а проверки перед коммитом автоматизировать хуками.