Close

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

Логотип Bitbucket
СМ. РЕШЕНИЕ

Изучите 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.

Люди сотрудничают друг с другом, используя стену со множеством инструментов

Блог Bitbucket

Рисунок: DevOps

Образовательные программы DevOps

Демонстрация функций в демо-зале с участием экспертов Atlassian

Как инструмент Bitbucket Cloud работает с Atlassian Open DevOps

Подпишитесь на информационную рассылку по DevOps

Thank you for signing up