Объедините два репозитория Git и сохраните историю
Я хочу продолжить еще один вопрос: Объединить два репозитория Git и сохранить главную историю
Мне удалось слить 2 разных репо в одно репо. Для этого мне понадобилась перезагрузка. Мастер прав, но Я также хочу сохранить историю слияния. Возможно ли это?
У меня есть 2 репозитория:
Это результат после перезагрузки. Время верхнего репо - это время восстановления. Исходная дата потеряна!
Вот как я это сделал:
# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init
# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
dir > Read.md
git add .
git commit -m "initial commit"
# Add a remote for and fetch the old RepoA
git remote add -f RepoA https://github.com/DimitriDewaele/RepoA
# Do the same thing for RepoB
git remote add -f RepoB https://github.com/DimitriDewaele/RepoB
# Rebase the working branch (master) on top of repoB
git rebase RepoB/master
# Rebase the working branch (master with RepoB) on top op repoA
git rebase RepoA/master
Возможно ли иметь что-то вроде этого? (раскрашенное решение!!!)
Я хотел бы сохранить исходное время + историю слияния.
ОБНОВЛЕНИЕ - ОТВЕТ
Ответ, который работал лучше всего для меня, работал с точками трансплантата. Но другие ответы также очень полезны в других случаях использования. Я добавил свои результаты в github, поэтому каждый может оценить.
Ответ 1: Лучшая работа в моем случае "Трансплантат" показал правильный рабочий ответ для меня.
GitHub: RepoGraft
Ответ 2 опция "replace" из "LeGEC" также дает хорошие результаты для некоторых вариантов использования. Одна аномалия осталась для меня:
GitHub: RepoHistory
Ответ 3: стоит добавить. Ответ от "VonC". Я не мог получить вариант "-preserve-merges working" в моем случае. Это может работать в других сценариях, но я не тестировал этого furtner.
Ответы
Ответ 1
Как вы обнаружили, rebase
- это не команда, которую вы хотите использовать для сшивания истории вместе (потому что она действительно перезаписывает историю). Ранняя Git имела функцию (хак), разработанную специально для того, что вы пытаетесь сделать: точки трансплантата. Еще лучше, с 1.6.5 вы можете использовать git replace --graft
:
git checkout master
git replace --graft $(git log RepoB/master --format=%H | tail -1) HEAD
git replace --graft $(git log RepoA/master --format=%H | tail -1) RepoB/master
git reset --hard RepoA/master
(git log RepoA/master --format=%H | tail -1
возвращает начальную фиксацию из RepoA
)
Технически вы можете пропустить первый replace
, если в действительности master
у вас нет ничего ценного, что даст только историю с RepoB + RepoA.
Эти команды создают записи в refs/replace/*
, которые можно нажать и вытащить, чтобы поделиться пересмотренной историей с другими. Или, если вы не заботитесь о сохранении SHA для RepoA/RepoB, вы можете сделать замены постоянными, запустив git filter-branch --all
, чтобы создать "реальный" набор коммитов желаемой линии.
Ответ 2
В git rebase есть два варианта, которые должны быть интересны вашему делу:
p
--preserve-merges
Воссоздание слияния вместо того, чтобы сплющить историю путем повторного воспроизведения, фиксирует введение слияния.
--committer-date-is-author-date
(из git am
)
По умолчанию команда записывает дату из сообщения электронной почты в качестве даты фиксации фиксации и использует время создания фиксации в качестве даты коммиттера. Это позволяет пользователю лгать о дате коммиттера, используя то же значение, что и дата автора.
Проверьте, если вторая перебаза не дает лучшего результата с:
git rebase -p --committer-date-is-author-date RepoA/master
Ответ 3
Этот ответ предлагает использовать другой способ RepoB
в качестве активного репо и иметь доступ к истории RepoA
:
использовать git replace
# start with a regular clone of the active repo :
$ git clone RepoB
# add repoA as a remote :
$ git remote add -f history https://github.com/DimitriDewaele/RepoA
# get hash of *initial* commit on repoB :
$ git log --oneline origin/master | tail -1
abcdef Initial commit
# get hash of last commit on repoA :
$ git log --oneline history/master | head -1
12345 Merge branch 'develop'
# use 'git replace' to tell git to stitch histories in the log :
$ git replace abcdef 12345
Примечание: эта операция выполняется на вашем компьютере, а не на удаленных репозиториях, поэтому ее следует повторять во всех новых клонов.
Вариант:
Вы можете нажать RepoA:master
на RepoB
под новым именем (например: RepoB:history/master
), затем вы можете использовать git replace abcdef history/master
, на коммит, которые все хранятся в RepoB
.
Ответ 4
Попробуйте выполнить следующие шаги:
-
Создайте новый пустой репозиторий New.
-
Сделайте начальную фиксацию, потому что она нужна, прежде чем мы сможем слить.
-
Добавление удаленного старого хранилища OldA.
-
Объединить OldA/master с New/master.
-
Создайте подкаталог OldA.
- Переместить все файлы в подкаталог OldA.
- Зафиксировать все перемещения файла.
- Повторите 3-6 для OldB.
A Powershell script для этих шагов может выглядеть так:
Предположим, что текущий каталог - это то место, где мы хотим создать новый репозиторий
Создать новый репозиторий
$git init
Прежде чем мы сделаем слияние, мы должны иметь начальную фиксацию, так что сделаем фиктивный фиксатор
$dir > deleteme.txt
$git добавить.
$git commit -m "Исходная фиктивная фиксация"
Добавьте пульт дистанционного управления и выберите старое репо
$git удаленный add -f old_a
Объединить файлы из old_a/master в новый /master
$git merge old_a/master
Очистите наш фиктивный файл, потому что нам он больше не нужен
$git rm.\deleteme.txt
$git commit -m "Очистить начальный файл"
Переместите файлы и папки old_a repo в подкаталог, чтобы они не столкнулись с другим репо, которое будет позже
$mkdir old_a
$dir -exclude old_a | % { git mv $_. Имя old_a}
Зафиксировать перемещение
$git commit -m "Переместить файлы old_a в subdir"
Сделайте то же самое для old_b
$git удаленный add -f old_b
$git merge old_b/master
$mkdir old_b
$dir -exclude old_a, old_b | % { git mv $_. Имя old_b}
$git commit -m "Переместить файлы old_b в subdir"
Передать ветку признаков из одного из старых репозиториев
$git checkout -b функция не работает
$git merge -s recursive -Xsubtree = old_a old_a/feature-in-progress
Надеюсь, что это поможет.