Смешивание двух хвостов истории на основе слияния в Git

У меня есть два репозитория Git с отдельными историями. После долгих исследований и долгих экспериментов я получил историю, которая выглядит следующим образом (используя YYYY-DD в качестве псевдохэшей коммитов):

HEAD---2016-09---2016-08---2016-07---2016-06
                     \-----2015-10---2015-09

Обратите внимание, что эта история имеет два «корня», поскольку последовательность 2015-10 была объединена/привита к середине. Важно то, что файлы в истории 2016-07 и истории 2015-10 содержат совершенно разные файлы, не имеющие ничего общего.

Я хотел бы объединить эту историю в одну полную строку коммитов, в исходном порядке коммитов от самого старого к самому новому, без пропусков (т. е. с исчезающим контентом, который снова появляется позже). Другими словами, вот что я хочу закончить с:

HEAD---2016-09---(2016-08)---2016-07---2016-06---2015-10---2015-09

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

Сначала я подумал сделать git replace --edit 2016-08, чтобы удалить родителя 2015-10, а затем git replace --edit 2016-06, чтобы поставить 2015-10 в качестве родителя (см. https://stackoverflow.com/a/37001417/421049), и, конечно же, после выполнения git filter-branch --tag-name-filter cat -- --all я получил единственную последовательность, которая выглядела так, как я хотел.

Но потом я задумался: поскольку содержание в двух «хвостах» было совершенно разным, не будет ли содержание в 2015-10 «исчезать» в 2016-06, а затем «возвращаться» в 2016-08? (Признаюсь, я не могу сразу проверить, получилось это или нет прямо сейчас; я стер эту попытку и слишком устал, чтобы делать это снова сегодня вечером.) Как я могу эффективно «слить» (в бытовом смысле) два хвоста , как если бы содержимое 2016-06 было добавлено к содержимому 2015-10? То есть любой коммит, заменяющий 2016-06, будет иметь все содержимое в 2015-10 вместе с содержимым исходного 2016-06? Однако я хочу, чтобы у нового 2016-06 была исходная дата фиксации, сообщение журнала и т. д.

Затем, после того, как это будет сделано, как мне удалить фиксацию "слияния" 2016-08 из истории, так как она больше не нужна? Я предполагаю, что могу использовать git rebase --onto 2016-08~ 2016-08 HEAD из https://stackoverflow.com/a/3705310/421049. Я попробовал это в первой попытке, но это не сработало --- я предполагаю, что это как-то связано с содержанием, которое "исчезло" в 2016-07 и 2016-06, потому что я просто перешил хвосты в другой последовательности, но я Точно сказать не могу.

Я извиняюсь, если это дублирующий вопрос, но после нескольких часов работы с этим и углубления в историю (и осторожного ковыряния в vi) у меня есть небольшая «усталость Git» за день. Заранее спасибо.


person Garret Wilson    schedule 14.05.2017    source источник


Ответы (1)


на упрощенном примере я смог

git checkout -b middle 2016-07
git rebase 2015-10

это воспроизводит ваши коммиты 2016-07 и 2016-06 поверх 2015-10

git checkout master

если ваш мастер указывает на 2016-09 или потомка

git rebase middle

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

если, как вы говорите, the files in the 2016-07 history and the 2015-10 history contain completely different files with nothing in common это должно дать вам хорошую историю без конфликтов.

person lucanLepus    schedule 14.05.2017
comment
Вау, спасибо --- я понятия не имею, что здесь происходит, но, похоже, это работает! Все выстроилось по порядку, и даже коммит слияния пропал. Единственная странность заключается в том, что в Bitbucket, в то время как все коммиты из коммита 2015-10 назад показывают правильную дату на временной шкале, все, начиная с 2016-06 вперед, показывает дату X минут назад в Bitbucket. Тем не менее, необработанные коммиты, кажется, имеют правильные даты, и они правильно отображаются в Git и TortoiseGit. Есть идеи, почему? В любом случае, я собираюсь добавить награду, чтобы вознаградить вас или кого-то еще, кто найдет ответ. - person Garret Wilson; 15.05.2017
comment
Я мало что знаю о битбакете, но это может быть связано с отслеживанием битбакета (и показом вам), когда на него фактически была отправлена ​​фиксация. Коммиты после 2015-10 годов были перебазированы, это изменило их родительские коммиты и, следовательно, идентификатор коммита — для битбакета их можно было считать новыми. 2015-10 - 2015-09 не изменились, все тот же идентификатор фиксации. Так что это может объяснить несоответствие в вашем отображении. - person lucanLepus; 15.05.2017
comment
Это имеет смысл. @lucanLepus, это так здорово --- Я просто жду, пока Stack Overflow позволит мне назначить награду за это, чтобы я мог вознаградить ваш ответ. В то же время, последнее, что мне нужно сделать, это изменить порядок нескольких коммитов (которые были введены вручную постфактум с правильными отметками времени задним числом). Я полагаю, я сделаю руководство, взаимодействующее с перебазированием --- там всего несколько коммитов не по порядку. Если у вас есть какие-либо советы по этому поводу, дайте мне знать. - person Garret Wilson; 15.05.2017
comment
изменение порядка с помощью интерактивной перебазировки довольно прямолинейно, версия командной строки позволяет вам просто перемещать строки, большинство графических интерфейсов делают перетаскивание. коммиты повторного знакомства, которые я никогда не делал, но, например. этот ответ должен помочь вам пройти через это - person lucanLepus; 15.05.2017