Перебазирование объединенной фиксации

#git

#git

Вопрос:

Вот моя история:

 * 8 [mybranch, origin/mybranch]
* 7
|
| * 6 [master, origin/master]
* | 5
* | 4
|/
* 3
* 2
* 1
  

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

 * 8 [mybranch, origin/mybranch]
* 7
* 6 [master, origin/master]
* 5
* 4
* 3
* 2
* 1
  

Возможно ли это?

Спасибо

Ответ №1:

Вы должны быть в состоянии сделать это просто с:

 $ git rebase master mybranch
  

Перебазирование выравнивает историю по умолчанию, и в приведенном выше заклинании говорится, что нужно перебазировать все, mybranch что еще не находится в master верхней части master . Результат должен выглядеть следующим образом:

 * 8' [mybranch]
* 5'
* 4'
* 6  [master, origin/master]
* 3
* 2
* 1
  

Это не совсем то, о чем вы просили, но я думаю, что это то, что вы хотите. master Ветка сохраняется, и затрагивается только ваша mybranch история.

Также обратите внимание, что фиксация 7 была потеряна в этом процессе. Коммиты слияния не должны отображаться в сжатой истории, поскольку они сами не должны вносить никаких изменений. Это верно даже для слияний, требующих разрешения конфликтов. При перебазировании одной ветви поверх другой конфликты будут возникать (и должны быть разрешены) в одном или нескольких коммит перебазированной ветви. Фактически работа, проделанная ранее коммитом слияния, складывается в перебазированные коммиты.

Предполагая mybranch , что другие что-то не используют, я думаю, что выполнение этой перебазировки в этом случае имеет смысл. Но я согласен с @amn: лучше избегать слишком много возиться с историей. Я думаю, что «более упрощенный» — лучшее описание линейной истории, чем описание ее как «более чистой», поскольку я думаю, что последнее имеет тенденцию подразумевать, что слияние является менее желательным рабочим процессом. Слияние более надежное и масштабируемое, чем перебазирование. С последним рабочим процессом вам действительно нужно создавать и тестировать каждый перебазированный коммит, тогда как с рабочим процессом слияния вам нужно только протестировать окончательный коммит слияния.

Ответ №2:

Вы должны создать новую историю. Самый прямой способ создать историю, которую вы хотели в первую очередь, это

 git rebase master mybranch
  

Это не та история, которую вы создали до сих пор, она другая, поэтому идентификаторы новых коммитов разные, но выглядит так

 * 8'    mybranch
* 5'
* 4'
* 6     master origin/master
* 3
* 2
* 1
  

в вашем репозитории, с вашими origin/mybranch и ссылками в любом другом репозитории, в который когда-либо извлекалась или вставлялась история, все еще ссылающаяся на старую, которую вы больше не любите. Если у вас есть хорошие связи со всеми, у кого есть копия этой старой истории, и они нормально выполняют выборку и перебазирование для переключения на новую, git push -f origin mybranch это, безусловно, лучший способ справиться с этим.

Чтобы максимально приблизиться к запрошенному вами буквальному результату, истории 12345678, также требуется переписать историю master ветвей и создать историю, которую вы бы не получили, если бы сделали все правильно с первого раза.

Другой вариант, особенно если существующая mybranch история попала в репозитории, с которыми вы мало общаетесь, — просто оставить все как есть и продолжить. Линейность хороша, но это все, что есть.

Комментарии:

1. Молодец! Я передумал по двум причинам: изменять отправленные коммиты очень опасно (в основном, если изменена структура), а перебазированные файлы не отражают существующий код — (извините за мой английский, если я не понял!)

2. Самая прямая последовательность команд git rebase master mybranch .

Ответ №3:

На самом деле вы не можете перемещать коммиты с помощью Git — родительская привязка к коммиту является частью его идентификатора — как только вы повторно создаете коммит, это уже не тот коммит, даже если набор изменений, которые он вносит, тот же. Git целенаправленно переваривает как можно больше коммита в свой идентификатор. Это помогает Git обеспечить целостность данных всего хранилища. Видите ли, повреждение коммита неизменно приведет к хэшу в другой идентификатор, который по замыслу будет распространяться по всему графику, поскольку Git не сможет разрешить родительские ссылки и в основном сообщит вам, что график поврежден.

В любом случае, ваши коммиты 6 7 и 8 в любом случае не будут напрямую участвовать в конечном графике как есть, но их эквиваленты (при условии, что вы разрешите потенциальные конфликты слияния во время их создания) будут представлены как 6' , 7' и 8' .

Что вам нужно сделать, так это «восстановить» (в кавычках, потому что, как описано выше, изменение родительского элемента больше не является тем же коммитом) 6 , на который, кстати, указывает master ветка, с:

 git rebase 5 master
  

Вышесказанное создает эквивалент изменений, внесенных с фиксацией 6 , но как если бы эти изменения были применены поверх фиксации 5 . Это может быть или не быть успешным без конфликтов слияния, которые полностью зависят от вас, чтобы разрешить путем редактирования файлов с конфликтующими областями содержимого.

Вы можете попробовать интерактивную перебазировку (добавить -i переключатель в приведенную выше команду), чтобы иметь полный контроль, но я подозреваю, что в вашем случае это не понадобится.

Итак, ваш коммит 6 останется таким, какой он есть, но другой коммит, назовем его 6' , появится в 5 качестве единственного родителя — продукта перебазирования. Коммиты по умолчанию отображаются в git log порядке их временной метки, поэтому ожидайте увидеть 6' вверху графика / списка.

Аналогичным образом вы затем перебазируете коммит, на который указывает by mybranch , поверх этого нового коммита 6' , который также является вашим новым master сейчас:

 git rebase master mybranch
  

После того, как вы закончите с обеими операциями перебазирования, у вас будет желаемый график коммитов. Имейте в виду, что, поскольку вы отслеживаете master ветку в своем репозитории «origin» (с origin/master помощью ), коммиты, на которые ссылается эта ветка, останутся, что может показаться запутанным, но необходимо, поскольку в противном случае git не сможет синхронизировать репозитории.

Я бы также рекомендовал вам не слишком много возиться с историей. Я знаю, это выглядит запутанно, но одна вещь, которую вы должны иметь в виду, это то, что человеческая работа часто бывает достаточно нелинейной, чтобы на самом деле создавать графики, которые мы затем склонны находить неопрятными. Но графики представляют только нашу работу и сами по себе не являются неопрятными. Этот конкретный бит — это только мое мнение, ваше может отличаться.