Обновление: обратите внимание, что ниже я предполагаю, что mytag
имеет только один родительский коммит, в противном случае это немного сложнее.
Во-первых, давайте предположим, что вы толькоесть один корневой коммит и что он f414f31
.(Если вам нужно найти все корневые коммиты, вы можете сделать это с помощью первой команды в этом ответе .)
Чтобы быть в безопасности, давайте создадим новую ветвь для этой операции, поэтому вашветвь master
остается такой, какой она была, на случай, если результаты будут не такими, как вы хотели бы.
git checkout -b new-master
Сбросьте эту ветку в корневой коммит:
git reset --hard f414f31
Теперьизмените рабочее дерево и индекс так, чтобы он совпадал с коммитом непосредственно перед mytag
:
git merge --squash mytag^
Затем создайте коммит из индекса - если вы хотите переписать корневой коммит, вы можете сделать этос git commit --amend
, но я бы предпочел сохранить один коммит между вашей старой и новой историями, поэтому я бы просто сделал:
git commit
Теперь вам нужно воспроизвести всю вашу работупоскольку (и в том числе) mytag
поверх этого коммита.Для этого и предназначен git rebase
, но по умолчанию он линеаризует всю историю, которую вы пытаетесь воспроизвести.Если у вас много коммитов слияний в истории с mytag
, это может быть причиной того, что вы видите много конфликтов.
Итак, если вы не возражаете против линеаризации истории, и вы можете исправить конфликты (возможно, с помощью git rerere
) вы могли бы просто сделать:
git rebase --onto new-master mytag^ master
Однако, если в этой истории есть слияния, и вы бы предпочли сохранить их, вы можете попробовать добавить -p
(--preserve-merges
) опция, которая попытается воссоздать их:
git rebase -p --onto new-master mytag^ master
В комментариях ниже вы задаете дополнительный вопрос о случае, когда у вас есть две корневые фиксации.В этом случае вы можете просто выбрать один из них и использовать git commit --amend
после сдавленного слияния, чтобы создать совершенно новый корневой коммит для переписанной истории.