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
Другие вопросы по тегам