
- •Введение
- •Об управлении версиями
- •Локальные системы управления версиями
- •Централизованные системы управления версиями
- •Распределённые системы контроля версий
- •Краткая история Git
- •Основы Git
- •Слепки вместо патчей
- •Почти все операции — локальные
- •Git следит за целостностью данных
- •Чаще всего данные в Git только добавляются
- •Три состояния
- •Установка Git
- •Установка из исходников
- •Установка в Linux
- •Установка на Mac
- •Установка в Windows
- •Первоначальная настройка Git
- •Имя пользователя
- •Выбор редактора
- •Утилита сравнения
- •Проверка настроек
- •Как получить помощь?
- •Итоги
- •Основы Git
- •Создание репозитория Git
- •Создание репозитория в существующем каталоге
- •Клонирование существующего репозитория
- •Запись изменений в репозиторий
- •Определение состояния файлов
- •Отслеживание новых файлов
- •Индексация измененных файлов
- •Игнорирование файлов
- •Просмотр индексированных и неиндексированных изменений
- •Фиксация изменений
- •Игнорирование индексации
- •Удаление файлов
- •Перемещение файлов
- •Просмотр истории коммитов
- •Ограничение вывода команды log
- •Использование графического интерфейса для визуализации истории
- •Отмена изменений
- •Изменение последнего коммита
- •Отмена индексации файла
- •Отмена изменений файла
- •Работа с удалёнными репозиторями
- •Отображение удалённых репозиториев
- •Добавление удалённых репозиториев
- •Fetch и Pull
- •Push
- •Инспекция удалённого репозитория
- •Удаление и переименование удалённых репозиториев
- •Работа с метками
- •Просмотр меток
- •Создание меток
- •Аннотированные метки
- •Подписанные метки
- •Легковесные метки
- •Верификация меток
- •Выставление меток позже
- •Обмен метками
- •Полезные советы
- •Автоматическое дополнение
- •Псевдонимы в Git
- •Итоги
- •Ветвление в Git
- •Что такое ветка?
- •Основы ветвления и слияния
- •Основы ветвления
- •Основы слияния
- •Основы конфликтов при слиянии
- •Управление ветками
- •Приемы работы с ветками
- •Долгоживущие ветки
- •Тематические ветки
- •Удалённые ветки
- •Отправка изменений
- •Отслеживание веток
- •Удаление веток на удалённом сервере
- •Перемещение
- •Основы перемещения
- •Более интересные перемещения
- •Возможные риски перемещения
- •Итоги
- •Git на сервере
- •Протоколы
- •Локальный протокол
- •Преимущества
- •Недостатки
- •Протокол SSH
- •Достоинства
- •Недостатки
- •Git-протокол
- •Достоинства
- •Недостатки
- •Протокол HTTP/S
- •Достоинства
- •Недостатки
- •Установка Git на сервер
- •Размещение «голого» репозитория на сервере
- •Малые установки
- •SSH доступ
- •Создание открытого SSH-ключа
- •Настраиваем сервер
- •Открытый доступ
- •GitWeb
- •Gitosis
- •Gitolite
- •Установка
- •Изменение параметров установки
- •Конфигурационный файл и правила контроля доступа
- •Продвинутый контроль доступа с запрещающими правилами
- •Ограничение push-ей на основе изменённых файлов
- •Персональные ветки
- •«Шаблонные» репозитории
- •Другие функции
- •Git-демон
- •Git-хостинг
- •GitHub
- •Настройка учётной записи
- •Создание нового репозитория
- •Импорт из Subversion
- •Добавление участников
- •Ваш проект
- •Ответвления проектов
- •Заключение о GitHub
- •Итоги
- •Распределённый Git
- •Распределённые рабочие процессы
- •Централизованный рабочий процесс
- •Рабочий процесс с менеджером по интеграции
- •Рабочий процесс с диктатором и его помощниками
- •Содействие проекту
- •Рекомендации по созданию коммитов
- •Отдельная маленькая команда
- •Отдельная команда с менеджером
- •Небольшой открытый проект
- •Большой открытый проект
- •Итоги
- •Сопровождение проекта
- •Работа с тематическими ветками
- •Применение патчей, отправленных по почте
- •Применение патчей с помощью команды apply
- •Применение патчей с помощью команды am
- •Проверка удалённых веток
- •Определение вносимых изменений
- •Интегрирование чужих наработок
- •Процессы слияния
- •Рабочие процессы с крупными слияниями
- •Рабочие процессы с перемещениями и отбором лучшего
- •Отметка релизов
- •Генерация номера сборки
- •Подготовка релиза
- •Команда shortlog
- •Итоги
- •Инструменты Git
- •Выбор ревизии
- •Одиночные ревизии
- •Сокращенный SHA
- •Небольшое замечание о SHA-1
- •Ссылки на ветки
- •RefLog-сокращения
- •Ссылки на предков
- •Диапазон коммитов
- •Две точки
- •Множество вершин
- •Три точки
- •Интерактивное индексирование
- •Добавление и удаление файлов из индекса
- •Индексирование по частям
- •Прятанье
- •Прятанье своих трудов
- •Откат применения спрятанных изменений
- •Создание ветки из спрятанных изменений
- •Перезапись истории
- •Изменение последнего коммита
- •Изменение сообщений нескольких коммитов
- •Переупорядочение коммитов
- •Уплотнение коммитов
- •Разбиение коммита
- •Крайнее средство: filter-branch
- •Удаление файла изо всех коммитов
- •Сделать подкаталог новым корнем
- •Отладка с помощью Git
- •Аннотация файла
- •Бинарный поиск
- •Подмодули
- •Начало использования подмодулей
- •Клонирование проекта с подмодулями
- •Суперпроекты
- •Проблемы с подмодулями
- •Слияние поддеревьев
- •Итоги
- •Настройка Git
- •Конфигурирование Git
- •Основные настройки клиента
- •core.editor
- •commit.template
- •core.pager
- •user.signingkey
- •core.excludesfile
- •help.autocorrect
- •Цвета в Git
- •color.ui
- •color.*
- •Внешние утилиты merge и diff
- •Форматирование и пробельные символы
- •core.autocrlf
- •core.whitespace
- •Настройка сервера
- •receive.fsckObjects
- •receive.denyNonFastForwards
- •receive.denyDeletes
- •Git-атрибуты
- •Бинарные файлы
- •Определение бинарных файлов
- •Получение дельты для бинарных файлов
- •Документы MS Word
- •Текстовые файлы в формате OpenDocument
- •Изображения
- •Развёртывание ключа
- •Экспорт репозитория
- •export-ignore
- •export-subst
- •Стратегии слияния
- •Перехватчики в Git
- •Установка перехватчика
- •Перехватчики на стороне клиента
- •Перехватчики для работы с коммитами
- •Другие клиентские перехватчики
- •Перехватчики на стороне сервера
- •update
- •Пример навязывания политики с помощью Git
- •Перехватчик на стороне сервера
- •Установка особого формата сообщений коммитов
- •Настройка системы контроля доступа для пользователей
- •Перехватчики на стороне клиента
- •Итоги
- •Git и Subversion
- •Настройка
- •Приступим к работе
- •Коммит в Subversion
- •Получение новых изменений
- •Проблемы с ветвлением в Git
- •Ветвление в Subversion
- •Создание новой ветки в SVN
- •Переключение активных веток
- •Команды Subversion
- •Просмотр истории в стиле SVN
- •SVN-Аннотации
- •Игнорирование того, что игнорирует Subversion
- •Заключение по Git-Svn
- •Миграция на Git
- •Импортирование
- •Subversion
- •Perforce
- •Собственная утилита для импорта
- •Итоги
- •Git изнутри
- •Сантехника и фарфор
- •Объекты в Git
- •Объекты-деревья
- •Объекты-коммиты
- •Хранение объектов
- •Ссылки в Git
- •HEAD
- •Метки
- •Ссылки на удалённые ветки
- •Pack-файлы
- •Спецификации ссылок
- •Спецификации ссылок для команды push
- •Удаление ссылок
- •Протоколы передачи
- •Тупой протокол
- •Умный протокол
- •Загрузка данных
- •Скачивание данных
- •Обслуживание и восстановление данных
- •Обслуживание
- •Восстановление данных
- •Удаление объектов
- •Итоги
Глава 8
Git и другие системы управления
версиями
Наш мир несовершенен. Как правило, вы не сможете моментально перевести любой проект, в котором вы участвуете, на использование Git. Иногда вам придется иметь дело с проектами, использующими другую систему контроля версий, и, в большинстве случаев, этой системой будет Subversion. Первая часть этого раздела научит вас обращаться с git svn —
встроенным в Git двухсторонним интерфейсом обмена с Subversion.
В какой-то момент, вы, возможно, захотите перевести свой существующий проект на
Git. Вторая часть раздела расскажет о том, как провести миграцию: сначала с Subversion,
потом с Perforce, и наконец, с помощью написания собственного сценария для нестандартных вариантов миграции.
8.1Git и Subversion
Внастоящее время большинство проектов с открытым исходным кодом, а также большое число корпоративных проектов, используют Subversion для управления своим исходным кодом.
Это самая популярная на текущий момент система управления версиями с открытым исходным кодом, история её использования насчитывает около 10 лет. Кроме того, она очень похожа на
CVS, систему, которая была самой популярной до Subversion.
Одна из замечательных особенностей Git — возможность двустороннего обмена с Subversion через интерфейс, называемый git svn. Этот инструмент позволяет вам использовать
Git в качестве корректного клиента при работе с сервером Subversion. Таким образом, вы можете пользоваться всеми локальными возможностями Git, а затем сохранять изменения на сервере Subversion так, как если бы использовали Subversion локально. То есть вы можете делать локальное ветвление и слияние, использовать индекс, перемещение и отбор патчей для переноса из одной ветви в другую (cherry-picking) и т.д., в то время, как ваши коллеги будут продолжать использовать в разработке подход времён каменного века. Это хороший способ протащить Git в рабочее окружение своей компании, чтобы помочь коллегам разработчикам стать более эффективными, в то время как вы будете лоббировать переход полностью на Git.
Интерфейс обмена с Subversion это ворота в мир распределённых систем управления версиями.
219

Глава 8 Git и другие системы управления версиями |
Scott Chacon Pro Git |
8.1.1 git svn
Базовой командой в Git для всех команд работающих с мостом к Subversion является git svn. Ей предваряется любая команда. Она принимает довольно порядочное число команд,
поэтому мы изучим из них, те которые наиболее часто используются, рассмотрев несколько небольших вариантов работы.
Важно отметить, что при использовании git svn, вы взаимодействуете с Subversion
— системой, которая намного менее «продвинута», чем Git. Хоть вы и умеете с лёгкостью делать локальное ветвление и слияние, как правило лучше всего держать свою историю в как можно более линейном виде, используя перемещения (rebase) и избегая таких вещей, как одновременный обмен с удалённым репозиторием Git.
Не переписывайте свою историю, попробуйте отправить изменения ещё раз, а также не отправляйте изменения в параллельный Git-репозиторий, используемый для совместной работы,
одновременно с другими разработчиками, использующими Git. Subversion может иметь только одну единственную линейную историю изменений, сбить с толку которую очень и очень просто.
Если вы работаете в команде, в которой некоторые разработчики используют Git, а другие
Subversion, убедитесь, что для совместной работы все используют только SVN-сервер — это сильно упростит вам жизнь.
8.1.2 Настройка
Для того, чтобы попробовать этот функционал в действии, вам понадобится доступ с правами на запись к обычному SVN-репозиторию. Если вы хотите повторить рассматриваемые примеры, вам нужно сделать доступную на запись копию моего тестового репозитория. Это можно сделать без труда с помощью утилиты svnsync, входящей в состав последних версий
Subversion (по крайней мере после версии 1.4). Для этих примеров, я создал новый Subversion-
репозиторий на Google Code, который был частичной копией проекта protobuf (утилита шифрования структурированных данных для их передачи по сети).
Чтобы мы могли продолжить, прежде всего создайте новый локальный репозиторий Subversion:
$ mkdir /tmp/test-svn
$ svnadmin create /tmp/test-svn
Затем разрешите всем пользователям изменять revprops — самым простым способом сделать это будет добавление сценария pre-revprop-change, который просто всегда завершается с кодом 0:
$ cat /tmp/test-svn/hooks/pre-revprop-change #!/bin/sh
exit 0;
$ chmod +x /tmp/test-svn/hooks/pre-revprop-change
Теперь вы можете синхронизировать проект со своей локальной машиной, вызвав svnsync init с параметрами задающими исходный и целевой репозиторий:
220

Scott Chacon Pro Git |
Раздел 8.1 Git и Subversion |
$ svnsync init file:///tmp/test-svn http://progit-example.googlecode.com/svn/
Эта команда подготовит процесс синхронизации. Затем склонируйте код выполнив:
$ svnsync sync file:///tmp/test-svn Committed revision 1.
Copied properties for revision 1.
Committed revision 2.
Copied properties for revision 2.
Committed revision 3.
...
Хотя выполнение этой операции и может занять всего несколько минут, однако, если вы попробуете скопировать исходный репозиторий в другой удалённый репозиторий, а не в локальный, то процесс займёт почти час, хотя в этом проекте менее ста коммитов. Subversion
вынужден клонировать ревизии по одной, а затем отправлять их в другой репозиторий — это чудовищно неэффективно, однако это единственный простой способ выполнить это действие.
8.1.3 Приступим к работе
Теперь, когда в вашем распоряжении имеется SVN-репозиторий, для которого вы имеете право на запись, давайте выполним типичные действия по работе с СУВ. Начнём с команды git svn clone, которая импортирует весь SVN-репозиторий в локальный Git-репозиторий.
Помните, что если вы производите импорт из настоящего удалённого SVN-репозитория, вам надо заменить file:///tmp/test-svn на реальный адрес вашего SVN-репозитория:
$ git svn clone file:///tmp/test-svn -T trunk -b branches -t tags
Initialized empty Git repository in /Users/schacon/projects/testsvnsync/svn/.git/ r1 = b4e387bc68740b5af56c2a5faf4003ae42bd135c (trunk)
Am4/acx_pthread.m4
Am4/stl_hash.m4
...
r75 = d1957f3b307922124eec6314e15bcda59e3d9610 (trunk) Found possible branch point: file:///tmp/test-svn/trunk => \
file:///tmp/test-svn /branches/my-calc-branch, 75
Found branch parent: (my-calc-branch) d1957f3b307922124eec6314e15bcda59e3d9610 Following parent with do_switch
Successfully followed parent
r76 = 8624824ecc0badd73f40ea2f01fce51894189b01 (my-calc-branch) Checked out HEAD:
file:///tmp/test-svn/branches/my-calc-branch r76
Эта команда эквивалентна выполнению для указанного вами URL двух команд — git svn init, а затем git svn fetch. Процесс может занять некоторое время. Тестовый проект имеет всего лишь около 75 коммитов, и кода там не очень много, так что скорее всего,
вам придётся подождать всего несколько минут. Однако, Git должен по отдельности проверить
221

Глава 8 Git и другие системы управления версиями |
Scott Chacon Pro Git |
и выполнить коммит для каждой версии. Для проектов, имеющих историю с сотнями и тысячами изменений, этот процесс может занять несколько часов или даже дней.
Часть команды -T trunk -b branches -t tags сообщает Git, что этот SVN-
репозиторий следует стандартным соглашениям о ветвлении и метках. Если вы используете не стандартные имена: trunk, branches и tags, а какие-то другие, то должны изменить эти
параметры соответствующим образом. В связи с тем, что такие соглашения являются общепринятыми,
вы можете использовать короткий формат, заменив всю эту часть на -s, заменяющую собой все эти параметры. Следующая команда эквивалента предыдущей:
$ git svn clone file:///tmp/test-svn -s
Таким образом, вы должны были получить корректный Git-репозиторий с импортированными ветками и метками:
$ git branch -a
*master my-calc-branch tags/2.0.2 tags/release-2.0.1 tags/release-2.0.2 tags/release-2.0.2rc1 trunk
Важно отметить, что эта утилита именует ваши ссылки на удалённые ресурсы по-другому.
Когда вы клонируете обычный репозиторий Git, вы получаете все ветки с удалённого сервера на локальном компьютере в виде: origin/[branch] — в пространстве имён с именем удалённого сервера. Однако, git svn полагает, что у вас не будет множества удалённых источников данных и сохраняет все ссылки на всякое, находящееся на удалённом сервере, без пространства имён. Для просмотра всех имён ссылок вы можете использовать служебную команду Git show-ref:
$ git show-ref
1cbd4904d9982f386d87f88fce1c24ad7c0f0471 refs/heads/master aee1ecc26318164f355a883f5d99cff0c852d3c4 refs/remotes/my-calc-branch 03d09b0e2aad427e34a6d50ff147128e76c0e0f5 refs/remotes/tags/2.0.2 50d02cc0adc9da4319eeba0900430ba219b9c376 refs/remotes/tags/release-2.0.1 4caaa711a50c77879a91b8b90380060f672745cb refs/remotes/tags/release-2.0.2 1c4cb508144c513ff1214c3488abe66dcb92916f refs/remotes/tags/release-2.0.2rc1 1cbd4904d9982f386d87f88fce1c24ad7c0f0471 refs/remotes/trunk
Обычный Git-репозиторий выглядит скорее так:
$ git show-ref
83e38c7a0af325a9722f2fdc56b10188806d83a1 refs/heads/master
222