Git format-patch/bundle для читабельного sneakernet "pull/push"
У меня есть две комнаты, в которых я поддерживаю некоторый исходный код с использованием git, комната разработчиков, где происходит большая часть разработки, и комната развертывания, в которой мы фактически используем программное обеспечение. Неизбежно некоторые изменения происходят и в комнате развертывания. Я хотел бы, чтобы обе комнаты имели одинаковую историю в git.
Ограничения:
- Из соображений безопасности две комнаты не подключены к сети.
- Только текстовые файлы (удобочитаемые) могут покинуть комнату развертывания.
Переместить изменения в комнату развертывания просто, используя git bundle
и отслеживание последнего коммита, который мы перенесли в комнату развертывания. Переместить изменения из комнаты сложнее из-за ограничения только текста.
Цель: перемещение совершает взад и вперед между двумя не связанными комнатами, как будто git pull
произошло, то есть идентичные хэши SHA1 в обеих комнатах.
До сих пор:
я пробовал
git format-patch
переместить изменения из deploy обратно в dev, но это не записывает слияния, и, следовательно, требует, чтобы для каждого непрерывного набора изменений генерировался другой набор исправлений вместе с некоторой записью о том, как воспроизвести точный коммит слияния, произошедший между ними. Существует некоторая дискуссия о создании различий для коммитов слияний, но, похоже, это не отражает фактическое происхождение, только изменения. Кажется, что исправления могут быть недостаточно богатым форматом для предоставления необходимой информации.Некоторые сценарии связки в текст могут быть использованы для преобразования пакета в формат без zip и удобочитаемого (ish) формата (и затем обратно после загрузки), но я не нашел никаких доказательств того, что такой сценарий существует.
Возможно, можно написать сценарий, чтобы пройти историю от какого-то общего предка до самого нового коммита и либо а) сделать патч, либо б) воссоздать слияние некоторых общеизвестных ссылок.
Резервный вариант: я всегда мог бы сжать коммиты, выходящие из комнаты развертывания, всего в один необработанный патч и разбить историю, но затем дальнейшие загрузки из dev->deploy сломали бы любые существующие рабочие копии. Не идеально.
Обновление: я верю git fast-export
может делать то, что мне нужно, хотя в большинстве примеров это работает на целые репозитории, а не на частичные истории, такие как git bundle
, У меня есть пример работающей игрушки, в котором я могу экспортировать частичную историю в устаревший клон, но он требует, чтобы я вручную отредактировал вывод быстрого экспорта, чтобы добавить from <sha1>
на первый коммит. Без этой модификации импорт создает разные sha1s и затем жалуется Not updating refs/heads/master (new tip <hash> does not contain <master's hash>)
,
Обновление 2: мой git fast-export
Решение действительно работает, но оно имеет проблему пропускной способности, так как оно работает, предоставляя совершенно новые файлы, а не отличия от предыдущих файлов. Это неприемлемо, поскольку мне действительно нужно прочитать все эти дополнительные строки.
1 ответ
Я никогда не находил идеального решения, но то, что мы делаем сейчас, похоже, работает. Основным недостатком является то, что коммиты в комнате развертывания изначально имеют один SHA1, который затем объединяется с другим SHA1 после объединения с комнатой разработки. Хорошая новость в том, что git
довольно легко распознает их, так как те же коммиты могут merge
прямо через них.
- Есть 3 контрольных пункта, которые мы должны отслеживать:
dev/master
который имеет новейшую разработку в комнате разработчиков.deploy/master
который имеет новейшую разработку в комнате развертывания.dev_deploy_common
который является последним коммитом, который разделяют две истории.
,
Когда мы перемещаем код из dev в развертывание (используя пакет), мы вносим коммиты как часть
dev_deploy_common
ветвь в комнате развертывания (git pull
вdev_deploy_common
), а затем изdeploy/master
сделатьgit merge dev_deploy_common
и разрешать и конфликтовать тут и там.Когда мы перемещаем код из deploy в dev (который должен быть текстовым файлом), мы делаем несколько дополнительных шагов:
Сначала мы перебазируем
deploy/master
наdev_deploy_common
так что все наши патчи смежные. Как правило, это легко, так как мы уже обрабатывали любые конфликты во время слияний, возникающие при переносе пакета из dev в развертывание.Во-вторых, мы генерируем набор патчей, используя
git format-patch -M25 -C25 --find-copies-harder -k --ignore-if-in-upstream
-M25 -C25 --find-copies-harder
параметры просто уменьшают размер выходного текста.-k
Опция сохраняет коммит предметов нетронутыми.--ignore-if-in-upstream
ограничивает наши коммиты только новыми, так какdev_deploy_common
,Результатом этого является
patchset.txt
Коллекция патчей. Этот файл можно просмотреть вручную, а затем перенести в комнату разработчиков.В комнате разработчиков мы импортируем набор патчей с помощью следующей команды:
git am -k -3 --keep-cr --committer-date-is-author-date patchset.txt
К сожалению, несмотря на то, что мы используем все команды, чтобы сохранить патч одинаковым, некоторые атрибуты меняются, в первую очередь, коммиттер. В результате "один и тот же" коммит будет иметь разные SHA1 в комнатах разработчиков и развертывания. Эта разница будет сохраняться до тех пор, пока мы не переместим пакет обратно в комнату развертывания.
При перемещении пакета из dev в развертывание,
merge
Операция (обычно) распознает идентичные патчи и плавно заменяет фиксацию на фиксацию в истории разработки. Смотрите Шаг 1.