Объединение двух репозиториев git одного проекта, связывание истории файлов - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть проект, который я начал давно, и сделал несколько коммитов. Затем проект был заброшен примерно на два года, в течение которых я забыл, что использовал в проекте контроль версий git. Я поднял его, скопировав все файлы на новый компьютер, и запустил новое git-репо с ~ 100 000 строк кода и десятками файлов, которые теперь имеют собственную длинную историю коммитов. Недавно я заново открыл старый репозиторий и попытался объединить историю коммитов обоих репо, , используя приведенные здесь инструкции.

Однако результат был неполным. Если я посмотрю на историю коммитов на github, коммиты из старого и нового репозитория не повреждены, но история каждого отдельного файла не распространяется на серию коммитов старого репозитория, все равно показывая их просто созданными во время коммита, созданного при создании. нового хранилища. Несколько файлов, которые не были перенесены, когда я вручную скопировал все для запуска нового репо, вообще не отображаются.

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

1 Ответ

0 голосов
/ 09 ноября 2018

Полагаю, вы следовали инструкциям верхнего ответа на вопрос, который вы связали. Это не лучшие шаги в этой ситуации.

У вас есть два сегмента истории для вашего проекта. Если предположить, что первый сегмент имел коммиты

A -- B -- C <--(master)

и второй сегмент имеет коммиты

D -- E -- F <--(master)

тогда полная история, которая ведет себя, как и ожидалось, будет выглядеть как

A -- B -- C -- D' -- E' -- F' <--(master)

(Примечание к записи: я заменил D на D' в объединенной истории и т. Д. Причины этого, возможно, носят технический характер и, вероятно, не сразу важны; в общем, это просто означает, что с точки зрения идентичность фиксации, D' отличается от D, потому что D' имеет C в качестве родителя, тогда как D нет. Но буква остается неизменной, чтобы показать, что D' представляет то же состояние код - т.е. тот же контент или TREE - как D.)

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

   A -- B -- C
              \
D -- E -- F -- f*

где f* - это коммит слияния (т. Е. Коммит с несколькими родителями), содержимое которого соответствует F, но который также перечисляет C как часть своей истории.

Проблема в том, что C является , а не , а затем распознается как часть D s истории. Фактически, правила фильтрации истории по умолчанию для git (например, для вывода журнала) полностью исключают A, B и C, потому что с точки зрения git состояние кода можно объяснить без них.

(Большинство текущих комментариев к вашему вопросу, в которых говорится о таких вещах, как эвристика подобия, - это красная сельдь. Мне кажется, что эти комментарии были написаны людьми, которые не очень внимательно смотрели на шаги, которые вы выполнили. )

Есть пара разных способов добраться до желаемого состояния. Если это репо, которое используется только вами, или если вы можете координировать действия со всеми пользователями репо для перезаписи истории, то операция «переопределение» будет хорошим решением. Это постоянное исправление, которое создаст цельную историю; но, поскольку это изменит историю веток текущего репо, важна координация с любыми другими пользователями. Проблема перезаписи общих историй, как правило, описана в документации git rebase в разделе «восстановление после восстановления исходных данных».

Другой альтернативой является использование git replace. Это имеет то преимущество, что это не перезапись истории, но у нее есть некоторые известные проблемы, и она требует небольшой специальной настройки в каждом клоне. (Если настройка не завершена, это просто означает, что конкретный клон не видит полную историю.)

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

Есть и другие варианты, и трудно сказать, какой из них лучше всего подходит для вашей ситуации. Если вы хотите более широко изучить возможности, вы можете обратиться к документации для git filter-branch и git replace.

...