git rebase после предыдущего слияния git

79

У меня такая ситуация:

  • Я создал clone(Y) из основного репозитория (X), потому что над Y работало много людей, мы не делали ничего, rebaseа только merges. Когда мы хотим доставить ( push) Y в X, мы хотели бы сделать rebase, чтобы все было красиво и чисто

Проблема в том, что при выполнении rebaseнас просят выполнить все слияния, которые мы уже сделали на предыдущих mergeшагах. Есть ли решение этой проблемы, кроме того, которое означает повторное слияние?

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

INS
источник
В: «Поскольку над Y работало много людей, мы не делали никаких перебазов, а только сливали», вы имеете в виду слияние с восходящим потоком, не так ли?
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

80

Ребазинг для получения "чистой" истории переоценен. Лучший способ сохранить историю - это просто выполнить слияние, а не перебазирование. Таким образом, если вам когда-нибудь понадобится вернуться к ревизии, она будет такой же, как и та, которую вы тестировали во время разработки. Это также решает вашу проблему с ранее решенными конфликтами слияния.

Если вы не заботитесь о сохранении истории, вы можете создать новую ветку от мастера, проверить ее, а затем выполнить a, git read-tree -u -m devчтобы обновить рабочее дерево в соответствии с devветкой. Затем вы можете зафиксировать все в одном большом коммите и как обычно слить его с мастером.

Карл Билефельдт
источник
1
То, что вы фактически сделали здесь, - это слияние. Новая ветка не нужна.
Исак Гилберт
1
@isakgilbert Это то же самое, только если слить с --squash. Обычное слияние добавит N или N + 1 коммитов к мастеру, если в ветке было N коммитов. Приведенное выше предложение или merge --squashвсегда будет добавлять в мастер только один коммит.
peterflynn
3
@ytpete, да, именно так. Я считаю, что приведенное выше - всего лишь окольный способ слияния-сквоша от разработчика к мастеру. «Создание новой ветки» просто указывает на то же место, что и мастер. «Зафиксировать все в одном большом коммите» - это просто сквош.
Исак Гилберт
3
Коммиты слияния шумят при попытке увидеть полный набор изменений в одной ветке. Больно извлекать разницу и смотреть на нее, когда чистая история упрощает.
Ajax
2
Я не могу не согласиться с тем, что «чистая» история переоценена. Его не переоценивают, это экономит время и делает вещи менее запутанными.
basickarl
121

git merge --squashтеперь мой предпочтительный способ перебазирования после большого объема работы и множества слияний ( см. этот ответ ). Если ветка, над которой вы работаете, вызывается my-branchи вы хотите выполнить перебазирование, masterпросто выполните следующие действия:

git checkout my-branch
git branch -m my-branch-old
git checkout master
git checkout -b my-branch
git merge --squash my-branch-old
git commit
Джон Леммон
источник
13

Два замечания:

  • вы можете перебазировать свою собственную (еще не запущенную) работу столько раз, сколько хотите, поверх только что загруженных коммитов.
  • Вы могли бы избежать конфликтов слияния (во время перебазирования), если бы вы активировалиgit rerere , что и делается для такого рода ситуаций.
    http://git-scm.com/images/rerere2.png Смотрите больше на git rerere.
VonC
источник
@lulian: в этом случае, если вам нужно перебазировать свою работу, я думаю, вам придется снова выполнять эти разрешения конфликтов слияния.
VonC
@krlmlr Спасибо. Я восстановил ссылку, добавил иллюстрацию и ссылку на страницу руководства этой команды.
VonC
8

Вы можете взять все изменения в своей ветке и поместить их в новую фиксацию masterследующим образом:

git diff master > my_branch.patch
git checkout master
patch -p1 < my_branch.patch

Затем подготовьте свои файлы и выполните фиксацию.

Дбастон
источник
1

Что касается воспроизведения конфликтов слияния, вы можете использовать git rerere для ведения базы данных о том, как конфликты слияния уже были решены, так что выполнение перебазирования, которое приводит к тем же конфликтам, будет иметь трудоемкие части, выполненные за вас автоматически.

https://hackernoon.com/fix-conflicts-only-once-with-git-rerere-7d116b2cec67

git config --global rerere.enabled true

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

Более формальная документация здесь: https://git-scm.com/docs/git-rerere

Аякс
источник