Git ветка из старых коммитов
Я исследовал это на SO и другой документации. Я пробовал перебазировать, объединять, собирать вишню и отделять головы.
После буквально 6 часов попыток сделать это, пришло время задать вопрос!
Вот с чего я начинаю:
A-B-C-D-E-F-G master
Вот что я хочу изменить на:
A-B F-G master
\ /
C-D-E dev
Самое близкое, что я пришел, это:
A-B C-D-E-F-G-H Main
\ /
C-D-E dev
\
F-G master
Мне пришлось добавить другое имя ветки и фиктивный коммит, чтобы ветвление работало вообще.
Но это хуже, чем без изменений.
Пожалуйста помоги!
ОБНОВЛЕНИЕ ПОСЛЕ ОТВЕТОВ
Спасибо за ответы.
Да, мое "что я хочу" было не очень понятно. Надеюсь, это проясняет это:
A-B - F-G master
\ /
C-D-E dev
Другими словами, "master" в F - это результат B плюс ветка "dev", слитая в нее.
ДО СИХ ПОР НЕ РАБОТАЕТ
Спасибо @frasertweedale за попытку ответа.
Я внимательно следовал вашим инструкциям и вот что я получаю в итоге:
A-B - "merge branch 'dev'"-G master
\ /
C-D-E dev
\
F-G-"merge branch 'dev'"-F-G
Я рад, что это сложно: потратив на это 7 часов, я не чувствую себя так плохо!
ЗАКЛЮЧИТЕЛЬНЫЙ РЕЗУЛЬТАТ Как сказал @frasertweedale, это именно то, что я хотел, за исключением висячих коммитов.
Итак, мне просто нужно избавиться от болтовни.
Для ясности я перерисовал ниже:
A-B - "merge branch 'dev'"-G2 master
\ /
C-D-E dev
\
F1-G1-"merge branch 'dev'"-F2-G2
И эта команда выполняет очистку:
git rebase -p --onto F1^ F1
Результат:
A-B - "merge branch 'dev'"-G2 master
\ /
C-D-E dev
"ветвь слияния 'dev'" содержит исходный F-коммит и, конечно, может быть так прокомментирована.
1 ответ
Если вы расширяете A
, B
и т. д. в соответствующие хеши коммитов, и что master
я сидела G
, первый шаг к ветке dev
в E
:
git branch dev E
Затем сброс master
в B
,
git reset --hard B
Далее, объединить dev
в master
, явно требуя фиксации слияния (иначе будет выполнено ускоренное dev
не отклонился от master
):
git merge --no-ff dev
master
теперь содержит коммиты до E
, Теперь вы можете выбрать оригинал F
а также G
совершает.
git cherry-pick F
git cherry-pick G
Теперь у вас есть что-то очень близкое к тому, что вы хотели; единственное отличие заключается в добавлении коммита слияния (B+E)
:
A-B - (B+E)-F-G master
\ /
C-D-E dev
Если вы сейчас хотите включить содержание F
в слиянии совершить (B+E)
Вы можете выполнить интерактивную перебазировку и соединить два коммита вместе. --preserve-merges
(псевдоним -p
Опция обязательна.
git rebase --interactive --preserve-merges B
Это вызовет редактор с содержимым, подобным следующему (хэши фиксации и итоги будут отличаться):
pick d4057bd c
pick 9419ef8 d
pick ad9e208 e
pick 120a90a Merge branch 'dev'
pick 61552ad f
pick c947153 g
Заменить pick
директива в начале F
совершить линию с squash
директива (в приведенном выше примере: squash 61552ad f
), затем сохраните и выйдите. Вам будет предложено сформировать новое сообщение фиксации из сообщений фиксации коммита слияния и F
и операция rebase будет завершена без дальнейшего вмешательства. После перебазирования вы получите именно ту историю репозитория, о которой вы просили (в вашем обновленном вопросе).
СОКРАЩЕННЫЙ СЦЕНАРИЙ
Следующий скрипт создает новый репозиторий с линейной историей, затем автоматически редактирует историю, используя (в основном) те же шаги, что и выше. Интерактивная перебазировка исключается, поэтому вмешательство пользователя не требуется.
mkdir foo ; cd foo
git init
for C in A B C D E F G; do
echo $C > $C
git add $C
git commit -m $C
git tag $C
done
git branch dev E
git reset --hard B --
git merge --no-ff dev
git cherry-pick F
git reset --soft HEAD~
git commit --amend -m F
git cherry-pick G
for C in A B C D E F G; do
git tag -d $C
done