Скачиваний:
0
Добавлен:
27.11.2023
Размер:
207.94 Кб
Скачать

Создание репозитория Git из репозитория Bazaar

Им просто пользоваться. Чтобы клонировать Bazaar репозиторий достаточно добавить префикс bzr::. Так как Git и Bazaar полностью клонируют репозиторий на ваш компьютер, то можно добавить клон Git к локальному клону Bazaar, но так делать не рекомендуется. Гораздо проще связать клон Git с центральным хранилищем — тем же местом, с которым связан клон Bazaar.

Предположим, что вы работали с удалённым репозиторием, находящимся по адресу bzr+ssh://developer@mybazaarserver:myproject. Чтобы его клонировать, нужно выполнить следующие команды:

$ git clone bzr::bzr+ssh://developer@mybazaarserver:myproject myProject-Git

$ cd myProject-Git

На текущий момент, созданный Git репозиторий использует дисковое пространство не оптимально. Поэтому вы должны очистить и сжать его, особенно если репозиторий большого размера:

$ git gc --aggressive

Ветки в Bazaar

Bazaar позволяет клонировать только ветки, при этом репозиторий может содержать их несколько, а git-remote-bzr может клонировать все. Например, чтобы клонировать ветку выполните:

$ git clone bzr::bzr://bzr.savannah.gnu.org/emacs/trunk emacs-trunk

Чтобы клонировать весь репозиторий, выполните команду:

$ git clone bzr::bzr://bzr.savannah.gnu.org/emacs emacs

Последняя команда клонирует все ветки репозитория emacs; тем не менее, конфигурацией допускается указывать только некоторые из них:

$ git config remote-bzr.branches 'trunk, xwindow'

Некоторые удалённые репозитории не позволяют просматривать список веток, поэтому их перечисление в конфигурации для команды клонирования может оказаться проще в использовании:

$ git init emacs

$ git remote add origin bzr::bzr://bzr.savannah.gnu.org/emacs

$ git config remote-bzr.branches 'trunk, xwindow'

$ git fetch

Игнорируем то, что игнорируется в .Bzrignore

При работе с проектом под управлением Bazaar вы не должны создавать файл .gitignore, потому что можете случайно добавить его в отслеживаемые, чем могут возмутиться другие пользователи, работающие с Bazaar. Решением может выступать создание файла .git/info/exclude, который может быть как символической ссылкой, так и обычным файлом. Позже мы рассмотрим пример решения этой проблемы.

Bazaar использует ту же модель игнорирования файлов что и Git, за исключением двух особенностей, не имеющих эквивалента в Git. Полное описание можно найти в документации. Эти два отличия следующие:

  1. !! позволяет игнорировать определённые шаблоны файлов, даже если они указаны со знаком !

  2. RE: в начале строки позволяет указать регулярное выражение Python. Git допускает только шаблоны оболочки.

Следовательно, возможны две ситуации:

  1. Если файл .bzrignore не содержит специфических префиксов, то можно просто создать символическую ссылку на него: ln -s .bzrignore .git/info/exclude

  2. Иначе, нужно создать файл .git/info/exclude и адаптировать его в соответствии с .bzrignore так, чтобы игнорировались те же файлы.

Вне зависимости от ситуации, вам нужно следить за изменениями в .bzrignore, чтобы файл .git/info/exclude всегда соответствовал .bzrignore. На самом деле, если в файл .bzrignore будут добавлены изменения в виде одной или нескольких строк с !! или RE: вначале, то Git просто не сможет их интерпретировать и вам понадобиться изменить файл .git/info/exclude так, чтобы игнорировались те же файлы. Более того, если файл .git/info/exclude был символической ссылкой, то сначала нужно его удалить, скопировать .bzrignore в .git/info/exclude и адаптировать последний. Однако, будьте осторожны с его созданием, потому что в Git невозможно повторно включить файл в индекс, если исключен родительский каталог этого файла.

Получение изменений с удалённого репозитория

Используя обычные команды Git можно получить изменения с удалённого репозитория. Предположим, что изменения находятся в ветке master, вы сливаете или перебазируете свою работу относительно ветки origin/master:

$ git pull --rebase origin

Отправка в удалённый репозиторий

Поскольку Bazaar так же имеет концепцию коммитов слияния, то проблем не возникнет при отправке такого коммита. Таким образом, вы можете работать в ветке, сливать изменения в master и отправлять их. Вы можете создавать ветки, делать коммиты и тестировать изменения как обычно. Наконец, вы отправляете проделанную работу в репозиторий Bazaar:

$ git push origin master

Предупреждение

Существуют ограничения на выполнение операций с удалённым репозиторием. В частности, следующие команды не работают:

  • git push origin :branch-to-delete (Bazaar не понимает удаление ссылок таким способом.)

  • git push origin old:new (будет отправлена 'old')

  • git push --dry-run origin branch (push будет выполнен)

Заключение

Поскольку модели Git и Bazaar схожи, то не так много усилий требуется для их совместной работы. Всё будет в порядке пока вы следите за ограничениями и знаете, что удалённый репозиторий изначально не Git.

Git и Perforce

Perforce — очень распространённая система контроля версий в корпоративной среде. Она появилась в 1995 году, что делает её самой старой СКВ, рассматриваемой в этой главе. Perforce разработан в духе тех времён; он предполагает постоянное подключение к центральному серверу, а локально хранится одна-единственная версия файлов. На самом деле, его возможности, как и ограничения, разрабатывались для решения вполне конкретных проблем; хотя многие проекты, использующие Perforce сегодня, выиграли бы от перехода на Git.

Существует два варианта совместного использования Git и Perforce. Первый — Git Fusion от разработчиков Perforce — позволяет выставлять поддеревья Perforce-депо в качестве удалённых Git репозиториев. Второй — git-p4 — клиентская обёртка над Perforce для Git; она не требует дополнительной настройки Perforce сервера.

Git Fusion

У создателей Perforce есть продукт, именуемый Git Fusion (доступен на http://www.perforce.com/git-fusion), который синхронизирует Perforce сервер с Git репозиторием на стороне сервера.

УСТАНОВКА

Для примера мы воспользуемся простейшим способом настройки Git Fusion — подготовленным образом для виртуальной машины с предустановленным Perforce демоном и собственно Git Fusion. Вы можете скачать образ на http://www.perforce.com/downloads/Perforce/20-User, а затем импортировать его в ваше любимое средство виртуализации (мы будем использовать VirtualBox).

Во время первого запуска вам потребуется сконфигурировать пароли трёх Linux пользователей (root, perforce и git) и имя хоста, которое будет идентифицировать компьютер в сети. По окончании вы увидите следующее:

Рисунок 145. Экран виртуальной машины Git Fusion

Запомните IP адрес, он пригодится в будущем. Далее, создадим пользователя Perforce. Выберите внизу опцию «Login» и нажмите Enter (или используйте SSH) и войдите как пользователь root. Используйте приведённые ниже команды, чтобы создать пользователя:

$ p4 -p localhost:1666 -u super user -f john

$ p4 -p localhost:1666 -u john passwd

$ exit

Первая команда откроет редактор для уточнения данных пользователя, но вы можете принять настройки по умолчанию, введя :wq и нажав Enter. Вторая команда дважды попросит ввести пароль. Это всё, что требовалось выполнить в оболочке ОС, можете завершить сессию.

Следующим шагом необходимо запретить Git проверять SSL сертификаты. Хотя виртуальная машина Git Fusion поставляется с сертификатом, он не привязан к домену и IP адресу виртуальной машины, так что Git будет отвергать соединения как небезопасные. Если вы собираетесь использовать эту виртуальную машину на постоянной основе, обратитесь к руководству по Git Fusion, чтобы узнать, как установить другой сертификат; для тестов же хватит следующего:

$ export GIT_SSL_NO_VERIFY=true

Теперь можете проверить что всё работает.

$ git clone https://10.0.1.254/Talkhouse

Cloning into 'Talkhouse'...

Username for 'https://10.0.1.254': john

Password for 'https://john@10.0.1.254':

remote: Counting objects: 630, done.

remote: Compressing objects: 100% (581/581), done.

remote: Total 630 (delta 172), reused 0 (delta 0)

Receiving objects: 100% (630/630), 1.22 MiB | 0 bytes/s, done.

Resolving deltas: 100% (172/172), done.

Checking connectivity... done.

На виртуальной машине уже настроен проект, который вы можете клонировать. Мы клонируем репозиторий по HTTPS протоколу, используя ранее созданного пользователя john; Git спросит пароль, но менеджер паролей запомнит его для последующих запросов.

НАСТРОЙКА FUSION

После установки Git Fusion вы, возможно, захотите настроить его. Это относительно несложно сделать, используя ваш любимый Perforce клиент; просто отобразите каталог //.git-fusion на Perforce сервере в ваше рабочее пространство. Структура файлов приведена ниже:

$ tree

.

├── objects

│   ├── repos

│   │   └── [...]

│   └── trees

│   └── [...]

├── p4gf_config

├── repos

│   └── Talkhouse

│   └── p4gf_config

└── users

└── p4gf_usermap

498 directories, 287 files

Каталог objects используется Git Fusion для отображения объектов Perforce в Git и наоборот, вам не следует ничего здесь трогать. Внутри расположен глобальный конфигурационный файл p4gf_config, а также по одному такому же файлу для каждого репозитория — эти файлы и определяют поведение Git Fusion. Заглянем в тот, что в корне:

[repo-creation]

charset = utf8

[git-to-perforce]

change-owner = author

enable-git-branch-creation = yes

enable-swarm-reviews = yes

enable-git-merge-commits = yes

enable-git-submodules = yes

preflight-commit = none

ignore-author-permissions = no

read-permission-check = none

git-merge-avoidance-after-change-num = 12107

[perforce-to-git]

http-url = none

ssh-url = none

[@features]

imports = False

chunked-push = False

matrix2 = False

parallel-push = False

[authentication]

email-case-sensitivity = no

Мы не будем вдаваться в назначение каждой опции, просто обратите внимание, что это обыкновенный INI файл, подобный тем, что использует Git для конфигурации. Файл, рассмотренный выше, задаёт глобальные опции, которые могут быть переопределены внутри специфичных для репозитория файлов конфигурации, типа repos/Talkhouse/p4gf_config. Если откроете этот файл, увидите секцию [@repo], переопределяющую некоторые глобальные настройки. Также, внутри есть секции, подобные этой:

[Talkhouse-master]

git-branch-name = master

view = //depot/Talkhouse/main-dev/... ...

Они задают соответствие между ветками Perforce и ветками Git. Названия таких секций могут быть произвольными; главное, чтобы они оставались уникальными. git-branch-name позволяет преобразовать пути внутри депо, которые смотрелись бы непривычно для Git пользователей. Параметр view управляет отображением Perforce файлов на Git репозиторий; используется стандартный синтаксис отображения видов. Может быть задано более одного отображения, как в примере ниже:

[multi-project-mapping]

git-branch-name = master

view = //depot/project1/main/... project1/...

//depot/project2/mainline/... project2/...

Таким образом, если ваше отображение включает изменения в структуре каталогов, вы можете реплицировать эти изменения здесь.

Последний файл, который мы обсудим, это users/p4gf_usermap; в нём задаётся отображение пользователей Perforce на пользователей Git. Возможно, вам не пригодится этот файл.

Когда Git Fusion преобразовывает набор изменений Perforce в Git коммит, он находит пользователя в этом файле и использует хранящиеся здесь адрес электронной почты и полное имя для заполнения полей «автор» и «применяющий изменения» в Git. При обратном процессе ищется пользователь Perforce с адресом электронной почты из поля «автор» Git коммитов и используется далее для изменения.

В большинстве случаев это нормальное поведение, но что будет, если соответствия выглядят так:

john john@example.com "John Doe"

john johnny@appleseed.net "John Doe"

bob employeeX@example.com "Anon X. Mouse"

joe employeeY@example.com "Anon Y. Mouse"

Каждая строка имеет формат <user> <email> "<full name>" и задаёт соответствие для одного пользователя. Первые две строчки отображают два разных адреса электронной почты на одного и того же пользователя. Это может быть полезным если вы фиксировали изменения в Git, используя разные адреса, или если вы поменяли адрес, но хотите отобразить эти изменения на одного и того же Perforce пользователя. При создании Git коммитов Perforce используется информация из первой совпавшей строки.

Последние две строки скрывают настоящие имена Боба и Джо в созданных Git коммитах. Это может быть полезным, если вы хотите отдать внутренний проект в open-source, но не хотите раскрывать информацию о сотрудниках. Адреса электронной почты и полные имена должны быть уникальными если вы хотите хоть как-то различать авторов в полученном Git репозитории.

РАБОЧИЙ ПРОЦЕСС

Perforce Git Fusion — это двунаправленный «мост» между Perforce и Git. Давайте посмотрим, как выглядит работа со стороны Git. Предполагается, что мы настроили отображение проекта «Jam», используя приведённую выше конфигурацию. Тогда мы можем клонировать его:

$ git clone https://10.0.1.254/Jam

Cloning into 'Jam'...

Username for 'https://10.0.1.254': john

Password for 'https://john@10.0.1.254':

remote: Counting objects: 2070, done.

remote: Compressing objects: 100% (1704/1704), done.

Receiving objects: 100% (2070/2070), 1.21 MiB | 0 bytes/s, done.

remote: Total 2070 (delta 1242), reused 0 (delta 0)

Resolving deltas: 100% (1242/1242), done.

Checking connectivity... done.

$ git branch -a

* master

remotes/origin/HEAD -> origin/master

remotes/origin/master

remotes/origin/rel2.1

$ git log --oneline --decorate --graph --all

* 0a38c33 (origin/rel2.1) Create Jam 2.1 release branch.

| * d254865 (HEAD, origin/master, origin/HEAD, master) Upgrade to latest metrowerks on Beos -- the Intel one.

| * bd2f54a Put in fix for jam's NT handle leak.

| * c0f29e7 Fix URL in a jam doc

| * cc644ac Radstone's lynx port.

[...]

В первый раз этот процесс может занять некоторое время. Git Fusion преобразовывает все наборы изменений Perforce в Git коммиты. Данные преобразуются локально на сервере, так что это вполне быстрый процесс; тем не менее, он может слегка затянуться, если у вас большая история изменений. Последующие скачивания требуют лишь инкрементального преобразования данных, таким образом скорость будет сравнима со скоростью работы обычного Git сервера.

Как видите, наш репозиторий выглядит так же, как выглядел бы любой другой Git репозиторий. В нём три ветки и Git предусмотрительно создал локальную ветку master, отслеживающую origin/master. Давайте немного поработаем и зафиксируем изменения:

# ...

$ git log --oneline --decorate --graph --all

* cfd46ab (HEAD, master) Add documentation for new feature

* a730d77 Whitespace

* d254865 (origin/master, origin/HEAD) Upgrade to latest metrowerks on Beos -- the Intel one.

* bd2f54a Put in fix for jam's NT handle leak.

[...]

Теперь у нас два новых коммита. Проверим, какие изменения внесли другие:

$ git fetch

remote: Counting objects: 5, done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 3 (delta 2), reused 0 (delta 0)

Unpacking objects: 100% (3/3), done.

From https://10.0.1.254/Jam

d254865..6afeb15 master -> origin/master

$ git log --oneline --decorate --graph --all

* 6afeb15 (origin/master, origin/HEAD) Update copyright

| * cfd46ab (HEAD, master) Add documentation for new feature

| * a730d77 Whitespace

|/

* d254865 Upgrade to latest metrowerks on Beos -- the Intel one.

* bd2f54a Put in fix for jam's NT handle leak.

[...]

Кто-то успел отправить свои изменения раньше нас! Конечно, из приведённого вывода команды git fetch не видно, но на самом деле коммит с SHA-1 6afeb15 был создан Perforce клиентом. Он выглядит так же, как и любой другой коммит, и это именно то, для чего создан Git Fusion. Давайте посмотрим, как Perforce обработает коммит слияния:

$ git merge origin/master

Auto-merging README

Merge made by the 'recursive' strategy.

README | 2 +-

1 file changed, 1 insertion(+), 1 deletion(-)

$ git push

Counting objects: 9, done.

Delta compression using up to 8 threads.

Compressing objects: 100% (9/9), done.

Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.

Total 9 (delta 6), reused 0 (delta 0)

remote: Perforce: 100% (3/3) Loading commit tree into memory...

remote: Perforce: 100% (5/5) Finding child commits...

remote: Perforce: Running git fast-export...

remote: Perforce: 100% (3/3) Checking commits...

remote: Processing will continue even if connection is closed.

remote: Perforce: 100% (3/3) Copying changelists...

remote: Perforce: Submitting new Git commit objects to Perforce: 4

To https://10.0.1.254/Jam

6afeb15..89cba2b master -> master

Со стороны Git всё работает как положено. Давайте посмотрим на историю файла README со стороны Perforce, используя p4v:

Рисунок 146. Граф ревизий Perforce после отправки данных из Git

Если вы ни разу не работали с Perforce это окно может показаться вам запутанным, но его концепция аналогичная gitk. Мы просматриваем историю файла README, так что дерево каталогов слева вверху показывает этот файл в разных ветках. Справа вверху мы видим граф зависимости разных ревизий файла, справа внизу этот же граф показан целиком для быстрого ориентирования. Оставшаяся часть окна отображает детали выбранной ревизии (в нашем случае это ревизия 2).

Граф выглядит в точности как в Git. У Perforce не было именованной ветки для сохранения коммитов 1 и 2, так что он создал «анонимную» ветку в каталоге .git-fusion. Git Fusion поступит так же для именованных Git веток не соответствующих веткам в Perforce, но вы можете задать соответствие в конфигурационном файле.

Большинство происходящей магии скрыто от посторонних глаз, а в результате кто-то в команде может использовать Git, кто-то — Perforce и никто не будет подозревать о выборе других.

ЗАКЛЮЧЕНИЕ ПО GIT-FUSION

Если у вас есть (или вы можете получить) доступ к Perforce серверу, Git Fusion — это прекрасный способ подружить Git и Perforce. Конечно, требуется небольшая работа напильником, но в целом всё довольно интуитивно и просто. Это один из немногих разделов в этой главе, где мы не будем предупреждать вас об опасности использования всей функциональности Git. Но Perforce не всеяден: если вы попытаетесь переписать опубликованную историю, Git Fusion отклонит изменения. Тем не менее, Git Fusion будет стараться изо всех сил, чтобы не нарушать ваших привычек при работе с Git. Вы даже можете использовать подмодули Git (хотя они и будут выглядеть странными для Perforce пользователей) и сливать ветки (на стороне Perforce это будет выглядеть как интеграция).

И даже в том случае, если вы не можете уговорить администратора настроить Git Fusion есть способ использовать Git и Perforce вместе.

Git-p4

Git-p4 — это двусторонний мост между Git и Perforce. Он работает на стороне клиента, так что вам не нужен будет доступ к Perforce серверу (разумеется, вам по-прежнему понадобятся логин и пароль). Git-p4 не так гибок и полнофункционален, как Git Fusion, но он позволяет совершать большинство необходимых действий.

Примечание

Исполняемый файл p4 должен быть доступен в PATH для использования git-p4. На момент написания книги он свободно доступен на http://www.perforce.com/downloads/Perforce/20-User.

НАСТРОЙКА

Мы будем использовать описанный выше образ виртуальной машины Git Fusion, но мы будем напрямую обращаться к Perforce, минуя Git Fusion.

Для того, чтобы использовать команду p4 (от которой зависит git-p4), вам нужно будет установить следующие переменные окружения:

$ export P4PORT=10.0.1.254:1666

$ export P4USER=john

НАЧАЛО РАБОТЫ

Как обычно при работе с Git, первая команда — это клонирование:

$ git p4 clone //depot/www/live www-shallow

Importing from //depot/www/live into www-shallow

Initialized empty Git repository in /private/tmp/www-shallow/.git/

Doing initial import of //depot/www/live/ from revision #head into refs/remotes/p4/master

В терминах Git мы получим так называемую «поверхностную» копию: выкачивается лишь последняя ревизия. Помните, Perforce не предназначен для раздачи всех ревизий всем пользователям. Этого достаточно, чтобы использовать Git как Perforce клиент, но этого недостаточно для других задач.

Как только клонирование завершится, у нас будет Git репозиторий:

$ cd myproject

$ git log --oneline --all --graph --decorate

* 70eaf78 (HEAD, p4/master, p4/HEAD, master) Initial import of //depot/www/live/ from the state at revision #head

Обратите внимание на наличие удалённого репозитория p4, соответствующего Perforce серверу; всё остальное выглядит как обычный клонированный репозиторий. Но давайте присмотримся повнимательней: на самом деле нет никакого удалённого репозитория!

$ git remote -v

В этом репозитории нет удалённых серверов. git-p4 создал несколько ссылок для представления состояния на сервере, и они выглядят как удалённый сервер для git log, но таковым не являются и вы не можете отправлять изменения в них.

РАБОЧИЙ ПРОЦЕСС

Что ж, приступим к работе. Предположим, вы сделали несколько изменений для очень важной фичи и готовы показать свои наработки остальным членам команды.

$ git log --oneline --all --graph --decorate

* 018467c (HEAD, master) Change page title

* c0fb617 Update link

* 70eaf78 (p4/master, p4/HEAD) Initial import of //depot/www/live/ from the state at revision #head

Мы подготовили два коммита для отправки на Perforce сервер. Давайте посмотрим, успели ли другие члены команды проделать какую-либо работу:

$ git p4 sync

git p4 sync

Performing incremental import into refs/remotes/p4/master git branch

Depot paths: //depot/www/live/

Import destination: refs/remotes/p4/master

Importing revision 12142 (100%)

$ git log --oneline --all --graph --decorate

* 75cd059 (p4/master, p4/HEAD) Update copyright

| * 018467c (HEAD, master) Change page title

| * c0fb617 Update link

|/

* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Кажется, успели: master и p4/master разошлись. Система ветвления в Perforce абсолютно непохожа на Git, отправка слияний в Perforce не имеет смысла. git-p4 рекомендует перемещать коммиты и даже предоставляет команду для этого:

$ git p4 rebase

Performing incremental import into refs/remotes/p4/master git branch

Depot paths: //depot/www/live/

No changes to import!

Rebasing the current branch onto remotes/p4/master

First, rewinding head to replay your work on top of it...

Applying: Update link

Applying: Change page title

index.html | 2 +-

1 file changed, 1 insertion(+), 1 deletion(-)

Вы, возможно, скажете что git p4 rebase это всего лишь сокращение для git p4 sync с последующим git rebase p4/master. На самом деле, эта команда немного умнее, особенно при работе с несколькими ветками, но догадка вполне верна.

Теперь наша история снова линейна и мы готовы отправить изменения в Perforce. Команда git p4 submit попытается создать новые Perforce ревизии для всех коммитов в Git между p4/master и master. Её запуск откроет ваш любимый редактор с примерно таким содержимым:

# A Perforce Change Specification.

#

# Change: The change number. 'new' on a new changelist.

# Date: The date this specification was last modified.

# Client: The client on which the changelist was created. Read-only.

# User: The user who created the changelist.

# Status: Either 'pending' or 'submitted'. Read-only.

# Type: Either 'public' or 'restricted'. Default is 'public'.

# Description: Comments about the changelist. Required.

# Jobs: What opened jobs are to be closed by this changelist.

# You may delete jobs from this list. (New changelists only.)

# Files: What opened files from the default changelist are to be added

# to this changelist. You may delete files from this list.

# (New changelists only.)

Change: new

Client: john_bens-mbp_8487

User: john

Status: new

Description:

Update link

Files:

//depot/www/live/index.html # edit

######## git author ben@straub.cc does not match your p4 account.

######## Use option --preserve-user to modify authorship.

######## Variable git-p4.skipUserNameCheck hides this message.

######## everything below this line is just the diff #######

--- //depot/www/live/index.html 2014-08-31 18:26:05.000000000 0000

+++ /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/index.html 2014-08-31 18:26:05.000000000 0000

@@ -60,7 +60,7 @@

</td>

<td valign=top>

Source and documentation for

-<a href="http://www.perforce.com/jam/jam.html">

+<a href="jam.html">

Jam/MR</a>,

a software build tool.

</td>

Это практически те же данные, что вы увидели бы, запустив p4 submit, за исключением нескольких строк в конце, любезно вставленных git-p4. git-p4 старается учитывать Git и Perforce настройки когда нужно предоставить имя для коммита, но в некоторых случаях вы захотите изменить его. Например, если коммит в Git был создан человеком, у которого нет Perforce аккаунта, вы всё равно захотите сделать автором коммита его, а не себя.

git-p4 вставил сообщение из коммита Git в содержимое набора изменений Perforce, так что всё что нам остаётся сделать — это дважды сохранить и закрыть редактор (по одному разу на каждый коммит). В результате мы получим такой вывод:

$ git p4 submit

Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/

Synchronizing p4 checkout...

... - file(s) up-to-date.

Applying dbac45b Update link

//depot/www/live/index.html#4 - opened for edit

Change 12143 created with 1 open file(s).

Submitting change 12143.

Locking 1 files ...

edit //depot/www/live/index.html#5

Change 12143 submitted.

Applying 905ec6a Change page title

//depot/www/live/index.html#5 - opened for edit

Change 12144 created with 1 open file(s).

Submitting change 12144.

Locking 1 files ...

edit //depot/www/live/index.html#6

Change 12144 submitted.

All commits applied!

Performing incremental import into refs/remotes/p4/master git branch

Depot paths: //depot/www/live/

Import destination: refs/remotes/p4/master

Importing revision 12144 (100%)

Rebasing the current branch onto remotes/p4/master

First, rewinding head to replay your work on top of it...

$ git log --oneline --all --graph --decorate

* 775a46f (HEAD, p4/master, p4/HEAD, master) Change page title

* 05f1ade Update link

* 75cd059 Update copyright

* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Выглядит так, словно мы только что выполнили git push, что на самом деле очень близко к тому, что произошло.

Обратите внимание, что во время этого процесса каждый коммит в Git превращается в отдельный набор изменений Perforce; если вы хотите слепить их воедино, вы можете сделать это с помощью интерактивного переноса коммитов до выполнения git p4 submit. Ещё один важный момент: SHA-1 хеши коммитов, превращённых в наборы изменений Perforce изменились: это произошло из-за того, что git-p4 добавил строку в конец каждого сообщения:

$ git log -1

commit 775a46f630d8b46535fc9983cf3ebe6b9aa53145

Author: John Doe <john@example.com>

Date: Sun Aug 31 10:31:44 2014 -0800

Change page title

[git-p4: depot-paths = "//depot/www/live/": change = 12144]

Что произойдёт если вы попробуете отправить коммит слияния? Давайте попробуем. Допустим, мы имеем такую историю:

$ git log --oneline --all --graph --decorate

* 3be6fd8 (HEAD, master) Correct email address

* 1dcbf21 Merge remote-tracking branch 'p4/master'

|\

| * c4689fc (p4/master, p4/HEAD) Grammar fix

* | cbacd0a Table borders: yes please

* | b4959b6 Trademark

|/

* 775a46f Change page title

* 05f1ade Update link

* 75cd059 Update copyright

* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

История в Git разошлась с Perforce на коммит 775a46f. В Git мы имеем два дополнительные коммита, затем слияние с состоянием Perforce, затем ещё один коммит. Мы собираемся отправить эту историю в Perforce. Давайте посмотрим, что произойдёт:

$ git p4 submit -n

Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/

Would synchronize p4 checkout in /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/

Would apply

b4959b6 Trademark

cbacd0a Table borders: yes please

3be6fd8 Correct email address

Флаг -n — это сокращение для --dry-run, который, в свою очередь, пытается вывести результат выполнения отправки, как если бы отправка на самом деле произошла. В этом случае, похоже мы создадим три ревизии в Perforce, по одной для каждой не являющейся слиянием коммита в Git. Звучит логично, давайте посмотрим что произойдёт на самом деле:

$ git p4 submit

[…]

$ git log --oneline --all --graph --decorate

* dadbd89 (HEAD, p4/master, p4/HEAD, master) Correct email address

* 1b79a80 Table borders: yes please

* 0097235 Trademark

* c4689fc Grammar fix

* 775a46f Change page title

* 05f1ade Update link

* 75cd059 Update copyright

* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

История стала линейной, словно мы переместили изменения перед отправкой (что на самом деле и произошло). Это означает, что вы можете свободно создавать ветки в Git, работать в них, сливать их, не боясь, что ваша история станет несовместима с Perforce. Если вы можете переместить изменения, вы можете отправить их на Perforce сервер.

ВЕТВЛЕНИЕ

Если в вашем Perforce проекте несколько веток, не переживайте: git-p4 может организовать работу с ними, не сложнее, чем с обычными Git ветками. Предположим, ваш Perforce репозиторий имеет следующую структуру:

//depot

└── project

├── main

└── dev

Также предположим, что ветка dev настроена следующим образом:

//depot/project/main/... //depot/project/dev/...

git-p4 может автоматически распознать эту ситуацию и выполнить нужные действия:

$ git p4 clone --detect-branches //depot/project@all

Importing from //depot/project@all into project

Initialized empty Git repository in /private/tmp/project/.git/

Importing revision 20 (50%)

Importing new branch project/dev

Resuming with change 20

Importing revision 22 (100%)

Updated branches: main dev

$ cd project; git log --oneline --all --graph --decorate

* eae77ae (HEAD, p4/master, p4/HEAD, master) main

| * 10d55fb (p4/project/dev) dev

| * a43cfae Populate //depot/project/main/... //depot/project/dev/....

|/

* 2b83451 Project init

Обратите внимание на @all в пути; она говорит git-p4 клонировать не только последнюю ревизию для указанного поддерева, но все ревизии, затрагивающие указанные пути. Это ближе к оригинальной концепции клонирования в Git, но если вы работаете с большим репозиторием, это может занять некоторое время.

Флаг --detect-branches указывает git-p4 использовать настройки веток Perforce для отображения на Git ветки. Если же таких настроек на Perforce сервере нет (что вполне корректно для Perforce), вы можете указать их git-p4 вручную, получив аналогичный результат:

$ git init project

Initialized empty Git repository in /tmp/project/.git/

$ cd project

$ git config git-p4.branchList main:dev

$ git clone --detect-branches //depot/project@all .

Задав конфигурационный параметр git-p4.branchList равным main:dev мы указали git-p4, что «main» и «dev» — это ветки, и что вторая является потомком первой.

Если мы теперь выполним git checkout -b dev p4/project/dev и зафиксируем в ветке dev некоторые изменения, git-p4 будет достаточно смышлёным, чтобы догадаться, в какую ветку отправлять изменения при выполнении git p4 submit. К сожалению, git-p4 не позволяет использовать несколько веток в поверхностных копиях репозиториев; если у вас есть большой проект и вы хотите работать более чем в одной ветке, вам придётся выполнять git p4 clone для каждой ветки, в которую вы хотите отправлять изменения.

Для создания и интеграции веток вам нужно будет использовать Perforce клиент. git-p4 может только забирать изменения из Perforce и отправлять линейную историю обратно. Если вы произведёте слияние двух веток в Git и отправите изменения в Perforce, сохранятся лишь данные об изменении файлов, все метаданные об исходных ветках, участвующих в интеграции, будут потеряны.

Соседние файлы в предмете Управление проектов программного обеспечения