Вы можете попробовать использовать файл трансплантата (.git/info/grafts
), где вы можете перезаписать родительский элемент коммита (например, первый из projectB
, имеющий для родителя самый последний из projectA
)
См. Также« Для чего нужны .git / info / grafts? » и « Как добавить прошлое в репозиторий git? », чтобы узнать больше об этой манипуляции.
скали комментарии к статье " Git: прививка репозиториев " (от пользователя SO Бен Штрауб )для конкретного примера.
Теперь мы хотим изменить первый коммит в репо «nuevo
» («New commit #1
»), чтобы его родитель был последним коммитом в репозитории.«Старый» репо («Старый № 3»).Время для какого-то вуду:
git fetch ../old master:ancient_history
Git позволяет вам получать данные из любого другого репозитория git, независимо от того, связано ли это репо или нет!Brilliant!Это оставляет нас с этим:
Обратите внимание, как мы переименовали старую ветвь мастера в Ancient_history.Если бы у нас этого не было, git попытался бы объединить их, и, вероятно, сдался бы с отвращением.
Теперь у нас все еще есть проблема.
Два дерева не связаны, и фактическиgit pull вообще не получит ветку древней истории.Нам нужен способ установить связь между ними.
В Git есть средство, называемое graft, которое в основном подделывает родительскую ссылку между двумя коммитами.
Чтобы сделать один, просто вставьте строку в.git/info/grafts
файл в этом формате:
[ref] [parent]
Обе они должны быть полными хэшами коммитов, о которых идет речь.Итак, давайте найдем их:
$ git rev-list master | tail -n 1
d7737bffdad86dc05bbade271a9c16f8f912d3c6
$ git rev-parse ancient_history
463d0401a3f34bd381c456c6166e514564289ab2
$ echo d7737bffdad86dc05bbade271a9c16f8f912d3c6 \
463d0401a3f34bd381c456c6166e514564289ab2 \
> .git/info/grafts
(в одну строку, как предложил от ssokolow )
echo $(git rev-list master | tail -n 1) $(git rev-parse ancient_history) > .git/info/grafts
Там.Теперь наша история выглядит следующим образом:
Клонирование этого репо приводит к следующему:
Woops.Оказывается, что прививки вступают в силу только для локального хранилища.Мы можем исправить это с помощью разумного применения git fast-import
:
$ git fast-export --all > ../export
$ mkdir ../nuevo-complete
$ cd ../nuevo-complete
$ git init
$ git fast-import < ../export
git-fast-import statistics: [...]
(в одну строку, как предложил ssokolow )
git filter-branch $(git rev-parse ancient_history)..HEAD
Это эффективно преобразует нашу «фальшивую» историческую ссылку в реальную.
Все инженеры должны будут повторно клонировать из этого нового хранилища, поскольку все хэши будут разными, но это небольшая цена за отсутствие простоев и полную историю.
As Qix комментарии ниже :
fast-import
, по-видимому, просто импортирует информацию git, но ничего не проверяет.
git init
изначально ставит вас на master, поэтому вам нужен git reset --hard HEAD
для проверки файлов после того, как вы fast-import
.