Есть ли чистый способ обработки двух оригинальных git-репозиториев, которые начинались с одного и того же контента?

Скажем, у меня есть два репозитория, которые были созданы из одного исходного содержимого. Например, если я использовал git для управления файлами конфигурации apache в /etc/apache2 и я запустил git init на машине-а и машине-б отдельно.

С тех пор я внес некоторые изменения в конфигурацию машины-b, которые я хотел бы применить к конфигурации на машине-a, не переписывая необычные вещи, такие как имена хостов и т. Д.

Если я сделаю это:

machine-a% remote add machine-b ssh://...
machine-a% git fetch machine-b

Я получаю все коммиты на машине-b, а GitX показывает совершенно отключенный набор коммитов, как я и ожидал.

Однако, если я пытаюсь объединить любое из изменений машины-b, я получаю конфликты на всех измененных строках.

Для моих целей это достаточно хорошо, но мне интересно, есть ли более чистое решение?

3 ответа

Решение

Возможно, вы захотите посмотреть на мерзавцы. Некоторая информация доступна здесь: http://git-scm.com/docs/git-filter-branch

По сути, вы хотите подделать родословную.

Вы сделали первоначальный коммит на обеих машинах - давайте назовем их "baseA" и "baseB". Затем вы создали второй коммит поверх этого с обеих сторон - 'secondA' и 'secondB'. Что вы хотите сделать, так это сказать git, что "secondB" не имеет "baseB" в качестве предка, а вместо этого "baseA" в качестве родителя.

Вы можете сделать это с помощью прививки. Например, поместите это в ваш файл.git/info/grafts:

secondB baseA

(но затем используя настоящие SHA). Теперь, если вы посмотрите в GitX, вы увидите, что истории связаны. Чтобы сделать изменение постоянным, вам нужно запустить git filter-branch.

Обновление из комментариев

Я не уверен, что вы сделали "правильно", хотя это сработает. Если вы сделаете то, что сделали, вы получите как историю:

 BaseA --- SecondA -- .. - ..  - Merge
   \ BaseB --- SecondB ... - .. /

Который будет работать (и слияние будет успешным без проблем). Однако, что немного приятнее, так это:

 BaseA --- SecondA -- .. - ..  - Merge
   \ SecondB ... - .. /

который в основном отбрасывает "BaseA" как коммит и устанавливает "BaseA" в качестве родителя для SecondB. Это должно быть возможно с использованием правила взяточничества, которое я вам сказал.

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

Если вы посмотрите на историю в GitX ("gitx master second_master"), вы увидите, что истории отключены. Если вы переместите файл.git/info/_grafts в.git/info/grafts, вы получите вторую красивую историю.

Я также добавил файл.git / info / false_grafts. Если вы используете это, вы получите историю, которую вы создали.

Если вы посмотрите на SHA в файле трансплантатов, то увидите, что файл _grafts в основном имеет следующее:

SecondB BaseA

и файл неправильный_графов имеет это:

BaseB BaseA

Это интересное использование Git; Я мог бы использовать его для работы с несколькими веб-сайтами, которые основаны на одной и той же кодовой базе вики, но имеют очень разные конфигурации.

Настройте репозиторий Git с исходным содержимым и создайте отдельные ветки для каждого компьютера, на котором хранится его текущая конфигурация. Клонируйте другой компьютер и установите каждый компьютер как удаленный для другого.

Теперь вы можете вносить изменения на одной машине и помещать их в свою ветку на другой машине, когда вы их фиксируете.

Если вы фиксируете общие элементы отдельно от не общих элементов, вы можете

$ git checkout [localmachine bracnch]
$ git cherry-pick [SHA1 of common commit1]
$ git cherry-pick [SHA1 of common commit2]

И, если вы не знаете, что вы хотите использовать повторно до фиксации на одной машине, вы можете использовать git add --patch вытащить отдельные дифференциалы из одной ветви и поставить их в соответствие другой ветке.

Для более чем двух машин / сайтов вы можете объединить общие изменения на MASTER и объединить изменения в MASTER на каждую из ветвей.

Как Git может определить, что такое "изменение конфигурации" и что такое "необычная вещь"? Есть ли только определенные файлы, которыми вы хотите поделиться между ними, например, файлы типа MIME?

Как насчет разделения общих частей на отдельные файлы и использования директивы Include Apache и добавления любых файлов, которые вы хотите игнорировать, в.gitignore?

Другие вопросы по тегам