СтатьиРазное

Несколько слов про git.
Dan Kruchinin (asgard)
24 июня 2007 01:07



Теги: git

Публикуется с согласия автора. Первая публикация — в блоге автора

Наверное все слышали о такой системе контроля версий, как git. Если всё же нет, то рекомендую для ознакомления прочитать соответсвующую статью в вики. К слову, под управлением гита живут такие проекты, как ядро linux, wine и x server.

Я попробую описать основные возможности этой системы, не особо углубляясь в детали реализации или технические тонкости. Зачем это нужно? Хм, ну во-первых ничего хорошего на русском про гит я не нашёл, во-вторых сами маны гита, написанные кстати — в большинтсве своём — Линусом, довольно, кхм, довольно малоподробны. Также хочу отметить, что сия заметка ни коим образом не претендует на исчерпывающую документацию. Это всего лишь некоторый quick start, не более. Что ж, поехали.

Wtf is git?:
Основные фича гита заключаются в удобном механизме ветвления, полного вьювинга хистори всех комитов и меньшем размере конечного репозитория, по сравнению с остальными vcs (здесь и далее — version control systems). Репозиторий гита — это всего лишь набор мелких патчей, где каждый патч (комит) имеет свой уникальный id — банальный хэш вида 6a9dffb8bc10f6344b2e2fcf3727c9d7195c714c. Пользователь данной vcs может локально создавать сколь угодно веток. В каждой ветке может находиться система, в том или ином своём состоянии давности, но об этом чуть ниже.

Where to get git?:
Последняя стабильная версия гита (src) может быть взята отсюда.
Если нет желания возиться с сорцами, можно установить гит из пакетов/портов/или-что-у-вас-там, как правило пакет носит имя git-core.

Start working:
Репозиторий гита — суть банальная директория с постфиксом .git. Так, например, репозиторий ядра linux имеет адрес git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git, где linux-2.6.git — директория.
Чтобы стянуть репозиторий того же ядра себе на машинку, можно сделать его «клон»(фактически, checkout):

git clone git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git linux-2.6

(Cледует заметить, что git — довольно молчаливая система, она с большой неохотой и довольно редко бует вам сообщать о том, что она делает в текущий момент времени. + клонирование ядра — долгая операция — благо, репозиторий весит порядка половины гига)
где linux-2.6 - директория, в которую будет помещён клон. Зайдя в директорию, можно посмотреть поддиректорию .git. Там и хранится вся нужная vcs информация.
Теперь заходим в директорию linux-2.6 и делаем команду git branch. Получаем что-то вроде:


* master
origin


Pвёздочкой отмечена активная ветка, т.е. в которой сейчас мы находимся.
master — стандартная ветвь репозитория
origin — ветвь, указывающая на удалённый репозиторий, как правило, напрямую с ней не работают.

Теперь делаем git tag -l (показать список тагов), в итоге получим что-то вроде этого:


v2.6.11
v2.6.11-tree
v2.6.12
v2.6.12-rc2
v2.6.12-rc3
v2.6.12-rc4
v2.6.12-rc5
v2.6.12-rc6
v2.6.13
v2.6.13-rc1
v2.6.13-rc2
v2.6.13-rc3
v2.6.13-rc4
v2.6.13-rc5
v2.6.13-rc6
v2.6.13-rc7
v2.6.14
v2.6.14-rc1
v2.6.14-rc2
v2.6.14-rc3
v2.6.14-rc4
v2.6.14-rc5
v2.6.15
v2.6.15-rc1
v2.6.15-rc2
v2.6.15-rc3
v2.6.15-rc4
v2.6.15-rc5
v2.6.15-rc6
v2.6.15-rc7
v2.6.16
v2.6.16-rc1
v2.6.16-rc2
v2.6.16-rc3
v2.6.16-rc4
v2.6.16-rc5
v2.6.16-rc6
v2.6.17
v2.6.17-rc1
v2.6.17-rc2
v2.6.17-rc3
v2.6.17-rc4
v2.6.17-rc5
v2.6.17-rc6
v2.6.18
v2.6.18-rc1
v2.6.18-rc2
v2.6.18-rc3
v2.6.18-rc4
v2.6.18-rc5
v2.6.18-rc6
v2.6.18-rc7
v2.6.19
v2.6.19-rc1
v2.6.19-rc2
v2.6.19-rc3
v2.6.19-rc4
v2.6.19-rc5
v2.6.19-rc6
v2.6.20
v2.6.20-rc1
v2.6.20-rc2
v2.6.20-rc3
v2.6.20-rc4
v2.6.20-rc5
v2.6.20-rc6
v2.6.20-rc7
v2.6.21
v2.6.21-rc1
v2.6.21-rc2
v2.6.21-rc3
v2.6.21-rc4
v2.6.21-rc5
v2.6.21-rc6
v2.6.21-rc7
v2.6.22-rc1
v2.6.22-rc2


таг — выделяет некоторую точку потока комитов, на которой может быть сделан останов. Таг хранит всю необходимую информацию для отката репозитория из любого состояния до той точки, которую он описывает. Так, например, таг v2.6.11 описывает, очевидно, состояние ядра linux-2.6.11, а таг v2.6.21 — linux-2.6.21. И вы без труда сможете перепрыгнуть с 2.6.11 на 2.6.21 без плясок с бубном и хора евнухов.

ветвь (branch) — всего лишь обстрактная модель, позволяющая на более удобном уровне работать с тагами. В репозитории может быть создано сколь угодно веток, где каждая ветвь привязана к какому-то тагу.

Пример:
git branch -b local v2.6.21
Эта команда создаст ветвь с именем local и привяжет к ней таг v2.6.21. Соответсвенно, в данной ветке будет находиться 21-ая версия ядрышка.

git branch -b old v2.6.11
То же самое, но новая ветвь теперь называется old и привязана к версии 2.6.11.

Теперь, предположим, что нам приспичило переключиться на ветвь old. Для этого мы делаем команду
git checkout old (внимание! checkout в случае гита - локальная команда, она не лезит в нет и не цепляется к удалённому репозиторию. Все действия происходят на локальной машине).

Поскольку гит суть набор патчей, checkout может проходить довольно долго, по той простой причине, что необходимые патчи просто накладываются в нужной последовательности. И при этом гит будет молчать, что несомненно действует на нервы =)

При checkout'e гит может ругнуться матом из-за того, что он по той или иной причине не может продолжить операцию. Случается такое, как правило, вот почему: ветки — всего лишь абстракция, файлы, так или иначе, хранятся в одной директории — linux-2.6 нашем случае. Т.о., если мы хотим прыгнуть с одной версии ядра на другую, переключая ветки, все действа — накладывание патчей — происходят в данной директории. И вполне может статься так, что если мы хотим прыгнуть с версии n на версию m, и в версии m появились какие-то новые файлы и/или были удалены старые, гит набросится на нас с благим матом. Решается это простым мержингом (как правило, автоматическим):

git checkout -m old

How to work effectively?:

Поскольку гит оперирует патчами, то новый комит, опять же, генерится в виде патча.
Для начала сделаем:
git checkout -m local
А после сделаем какие-нибудь изменения в файле init/main.c
Допустим мы хотим получить патч, который апдейтит main.c в ядре версии 2.6.21.

git branch -b v2.6.21 v2.6.21
git diff v2.6.21:init/main.c init/main.c > ../my-fucking-amazing-patch.patch


Так вот и получается патч =)

Ещё одна полезная команда - git log. Она показывает лог всех комитов в данной ветке. Также её можно натравить на любой отдельный файл, и она покажет историю комитов только для данного файла:
git log init/main.c

Допустим, что вам не понравились ваши изменения в ветке local, и вы решили откатиться каноническую 2.6.21. Для этого существует команда git reset. Для нашего случая она будет выглядеть так:
git reset --soft v2.6.21
И у нас в local снова 2.6.21.

How to update?:

для апдейта существуют 2 команды:
git pull
git fetch


git fetch — тупо извлекает набор патчей и добавляет новые таги в список тагов, который может быть просмотрен git tag -l

git pull — делает то же самое, что и git fetch + пытается замержить новый таг на ветвь, в которой вы находитесь в данный момент.

После апдейта рекомендуется делать команду git fsck-objects, которая проверит объекты репозитория на возможные косяки.

Часто случается, что, обновив репозиторий, вы заметили косяки в последний версии программы. Вы, естественно, хотите их выявить и пофиксить, но не знаете как. Для этого существует команда git bisect. Принцип работы следуюший:

git bisect start
git bisect bad /* пометить текущую ветку, как косячную */
git bisect good v2.6.21 /* пометить ветку 2.6.21, как хорошую */

После этого гит постарается найти потенциально опасные комиты. Вот вроде и всё.

More features:

У гита есть всевозможные user-friendly обёртки, которые можно найти через гугл, также море транспортов в другие виды vcs, удобный веб-интерфейс (пример можно видеть на http://git.kernel.org/).
Самая мега-свежая версия гита может быть скачана из гита =) --> git://git.kernel.org/pub/scm/git/git.git

Some minuses:

  • молчалив(я нервничаю, когда программа висит более 30 минут и нечерта не пишет)
  • медленное переключение с ветки на ветку


See also:
git help -a (а дальше man по интересующей команде вида man git-command. прим: man git-pull)
gitwiki
git documentation


Теги: git