Git и Perforce: рабочий процесс интеграции
Представим такой сценарий: ваша команда работает отдельно в репозитории Git, а часть организации все еще использует Perforce для управления фрагментами той же самой базы кода. Команды, работающие с Perforce, не собираются переходить на Git, как это сделала (по многим веским причинам) ваша команда. Вам важно наладить непрерывный обоюдный обмен между базами кода, чтобы делиться улучшениями, разработанными в каждой версии. Кроме того, желательно, чтобы это происходило без больших затрат времени и усилий, замедляющих работу команды.
В этом вам поможет данное руководство. В компании TomTom такая синхронизация выполняется один раз в релиз, то есть каждые полтора месяца.
-- Статья написана в соавторстве с Андреа Карлевато, Адольфо Бульфони и Кшиштофом Карчевским, которые любезно описали процесс работы с Git, принятый в подразделении NavApps компании TomTom. --
Предпосылки
Будем исходить из того, что вам уже знакомы основы Git и рабочий процесс с функциональными ветками. Если нет, посмотрите практическое видеоруководство или этот вебинар. Возвращайтесь, когда будете готовы, а мы вас подождем.
При выполнении интеграций нужно учитывать ряд нюансов, поэтому советуем действовать с большой осторожностью. Если вы готовы, приступим!
Установка git p4
Сначала нужно установить мост. Проверьте его наличие, набрав в командной строке:
git p4
Если в системе появляется сообщение о том, что инструмент git p4
не установлен, загрузите файл git-p4.py и поместите его в папку, указанную в переменной PATH
, например в папку ~/bin
. (Естественно, понадобится также установить Python, чтобы все заработало.)
Сделайте файл исполняемым:
chmod +x git-p4.py
Отредактируйте файл ~/.gitconfig
, добавив следующую запись:
[alias]
p4 = !~/bin/bit-p4.py
Снова запустите git p4
. Теперь ошибок быть не должно. Инструмент установлен.
Связанные материалы
Перемещение полного репозитория Git
СМ. РЕШЕНИЕ
Изучите Git с помощью Bitbucket Cloud
Обзор рабочего процесса
Первоначальное клонирование
У проектов в P4
может быть огромная история, поэтому команда выбирает точку отсечки для начала синхронизации, тем самым экономя много времени и места. git p4
позволяет выбрать список изменений, с которого начнется отслеживание:
git p4 clone //depot/path/project@<earlier-cutoff-point>,<latest-changelist>
- Теперь можно выполнить синхронизацию и убедиться, что все наборы изменений появились в локальном репозитории:
git p4 sync
Команда sync
находит в P4
новые изменения и импортирует их в Git в качестве коммитов.
- Дадим имя
p4-integ
ветке, которую будем использовать для непосредственного взаимодействия с Perforce. В данном случае для этого мы создадим ответвление отremotes/p4/main
:
git checkout -b p4-integ origin/p4/main
Последующая быстрая синхронизация (или «приманка и подмена»)
После того как будет завершен первый импорт, синхронизацию git->p4
можно будет выполнять с помощью следующих команд:
git checkout p4-integ
git p4 sync
Они работают, но порой медленно. Чтобы ускорить синхронизацию, можно воссоздать ссылки
, идентичные тем, что использовались в последней интеграции. Этот способ также хорош тем, что любой новый разработчик, отвечающий за интеграцию, начинает с правильного коммита или списка изменений.
Вот как это делается.
- Уберите прежние исходные (или устаревшие)
ссылки
на удаленный репозиторийP4
(необязательный шаг):
git symbolic-ref -d refs/remotes/p4/HEAD
git update-ref -d refs/remotes/p4/main
- Создайте искусственные («поддельные») удаленные ссылки, указывающие на последний коммит в ветке
p4-integ
репозиторияorigin
:
git update-ref refs/remotes/p4/main remotes/origin/p4-integ
git symbolic-ref refs/remotes/p4/HEAD refs/remotes/p4/main
Единственный недостаток такой ускоренной синхронизации заключается в том, что ветку нужно явно указать в git p4
, поэтому последняя команда будет выглядеть так:
git p4 sync --branch=refs/remotes/p4/main
В git p4
идентификаторы коммитов Git и изменения P4 сопоставляются путем аннотирования коммитов с помощью метаданных:
Merge pull request #340 in MOB/project from bugfix/PRJ-3185 to develop
Squashed commit of the following:
commit c2843b424fb3f5be1ba64be51363db63621162b4
Author: Some Developer
Date: Wed Jan 14 09:26:45 2015 +0100
[PRJ-3185] The app shows ...
commit abc135fc1fccf74dac8882d70b1ddd8a4750f078
Author: Some Developer
Date: Tue Jan 13 14:18:46 2015 +0100
[PRJ-3185] The app shows the rating ...
[git-p4: depot-paths = "//depot-mobile/project/": change = 1794239]
Обратите внимание, что в более новой версии git p4
метаданные, которые связывают коммиты Git со списками изменений P4
, хранятся в примечаниях к коммитам, а не в комментариях к ним. Команду TomTom это обновление не обрадовало, поскольку теперь проверка номеров списков изменений отнимает больше времени.
Перенос изменений из git в Perforce
После завершения быстрой синхронизации, описанной выше, можно отправить изменения из Git
в Perforce.
Для начала нужно перебазировать ветку p4-integ
на ветку remotes/p4/main
, чтобы первая получила изменения из второй:
git checkout p4-integ
git p4 rebase
Теперь p4-integ
содержит все новые изменения из Perforce, и можно обновить основную ветку
.
- После этого выполните простые команды:
git checkout main
git merge develop
- Убедитесь, что все последние теги загружены в локальный репозиторий:
git fetch --tags
- Воспользуйтесь временной
очисткой
, если нужно удалить коммиты, которые уже находятся вP4
(они отмечены тегомP4
). Если коммиты пропускать не нужно, выполните автоматическое перебазирование, чтобы сделать историю линейной:
git checkout -b cleanup #branching off from main
git rebase -s recursive -X theirs tag/last-p4-integ
- То же самое можно сделать путем интерактивного перебазирования:
git rebase -i tag/last-p4-integ
- Используйте команду
cherry-pick
, чтобы отобрать новые коммиты и поместить их в веткуp4-integ
. Мы поступили так, потому что не знаем наверняка, могут лиосновная ветка
и веткаdevelop
вGit
выступать полноценными предками дляp4-integ
. В компании TomTom, например, это уже не так.
git checkout p4-integ
git cherry-pick tag/last-p4-integ..cleanup
- Отправьте изменения в
P4
и синхронизируйте веткуp4-integ
:
git p4 submit
git p4 sync --branch=refs/remotes/p4/main
git reset --hard refs/remotes/p4/main
- Удалите временную ветку перебазирования:
git branch -D cleanup
- Удалите указатель на последнюю точку интеграции (тег) в локальном и удаленном репозиториях:
git tag -d tag/last-p4-integ
git push origin :refs/tags/tag/last-p4-integ
- Обновите тег
last-p4-integ
так, чтобы он указывал на новую точку интеграции вP4
:
git checkout develop
git tag -a tag/last-p4-integ -m "tag pointer to last develop commit integrated with p4"
git push origin main
git push origin tag/last-p4-integ
git push origin p4-integ
Запустите тестирование базы кода в P4
, чтобы убедиться в отсутствии проблем из-за интеграции.
Перенос изменений из Perforce в git
Эту операцию нужно выполнять после отправки кода git->P4
. После того как тесты в P4
будут успешно пройдены, вы сможете перенести изменения из P4
в Git
с помощью следующих команд:
git checkout p4-integ
git p4 sync --branch=refs/remotes/p4/main
git p4 rebase
- Ниже показан полезный прием, который позволит применить надежную стратегию слияния изменений с «их» стороны (theirs), склеив входящие изменения в один коммит. Вот как это выглядит:
git checkout -b p4mergebranch #branching off from p4-integ
git merge -s ours main ## ignoring all changes from main
git checkout main
git merge p4mergebranch --squash
git commit -m "Type your integration message"
git branch -D p4mergebranch
- Завершив предыдущий шаг, объедините изменения с веткой
develop
:
<p>Bitbucket has the following space stations:</p>
<p>
<b>Earth's Moon</b><br>
Headquarters
</p>
С тех пор как мы отобрали изменения из ветки develop
, наверняка появились новые. Их слияние мы выполним в первую очередь. Перед этим важно обновить тег last-p4-integ
, чтобы он указывал на правильный коммит (ни в коем случае не на коммит слияния в ветку develop). Безопаснее всего будет отметить тегом текущее состояние основной ветки
.
- Удалите старый тег в локальном и удаленном репозиториях:
git tag -d tag/last-p4-integ
git push origin :refs/tags/tag/last-p4-integ
- Создайте тег в новой точке:
git checkout main
git tag -a tag/last-p4-integ -m "tag pointer to last develop commit integrated with p4"
- Теперь отправьте
основную ветку, а также ветки develop, p4-integ
и тегtag/last-p4-integ
в репозиторийorigin
.
Заключение
Вот так можно синхронизировать результаты работы команд, ведущих разработку в Git и Perforce. Описанный нами процесс уже давно отработан в TomTom и не доставляет серьезных проблем, хотя на его поддержание уходит довольно много времени и сил. Если у вас есть возможность, рекомендуем все же полностью перейти на Git.
Если вы поддерживаете двухстороннюю синхронизацию другим способом, оставьте комментарий к статье или отправьте сообщение в Twitter на @durdn либо @atlassiandev. Мне будет очень любопытно ознакомиться с вашими идеями.
Еще раз выражаю благодарность Андреа Карлевато, Адольфо Бульфони и Кшиштофу Карчевскому.
Поделитесь этой статьей
Следующая тема
Рекомендуемые статьи
Добавьте эти ресурсы в закладки, чтобы изучить типы команд DevOps или получать регулярные обновления по DevOps в Atlassian.