Почему git rebase воспроизводит фиксацию ветви функций одну за другой?

#git #github #rebase

#git #github #перебазирование

Вопрос:

Я новичок в командах git и недавно перешел к команде git rebase. У меня возникли сомнения относительно того, почему команда git rebase воспроизводит коммиты ветки функций один за другим, а не просто воспроизводит последнюю фиксацию в ветке функций.

Это был мой сценарий в проекте, где я работал:

 M1 --- M2 --- M3 --- M4
       |
       M2 --- F1 --- F2 --- F3
  

Мы были 4 разработчиками, работающими над проектом, и я разветвил проект из upstream / master в точке M2.

Я начал работать над своей функцией и начал добавлять коммиты. Фиксация F1 была с некоторым базовым кодом. Затем фиксация F2 была исправлением некоторых ошибок для фиксации F1, и аналогично, фиксация F3 была исправлением ошибки для кода в F2, а F3 был моим последним кодом, готовым к использованию.

Тем временем другие разработчики завершили свою функцию, и их код был объединен в upstream / master. Теперь я должен поместить свой код поверх их функции, которая является M4. Теперь приведенная ниже часть — это мое понимание перебазирования git, и я могу ошибаться:

Я проверил ветку функций и выполнил перебазирование git с помощью upstream / master, что как бы поместило мою ветку функций поверх M4 и начало воспроизводить мои коммиты (F1, F2 и F3) один за другим. Я получил конфликты при воспроизведении F1 и разрешил их. Поскольку F2 был исправлением ошибки в F1, я снова получил похожие конфликты в том же месте и снова разрешил их. Наконец, я снова столкнулся с похожими конфликтами в том же месте, когда был воспроизведен F3. Я разрешил конфликты, и все было в порядке.

Но вместо воспроизведения коммитов F1, F2, F3, если бы git попытался поместить только последний коммит моей ветки функций поверх M4, тогда мне пришлось бы разрешать конфликты только один. [Поскольку мой код в F3 также будет содержать код для F1 и F2]. Итак, зачем эти дополнительные повторы.

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

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

1. Вот как работает перебазирование. Вы ищете git merge . Просто выполните проверку в главной ветке и выполните git merge {yourbranch}

2. Вы должны рассматривать коммит как нечто, что вносит изменения в файлы (посмотрите, что такое исправление), и вы поймете, что для получения всех изменений всех коммитов вы должны применять изменения, вносимые каждым коммитом, один за другим (а перебазирование — это применение всех пакетов коммитов)

Ответ №1:

Вы должны сказать Git, чтобы он уничтожал все коммиты, кроме вашего последнего коммита, чтобы достичь того, чего вы ожидаете от необходимости разрешать конфликты только один раз.

Чтобы сделать это, инициируйте интерактивную перебазировку поверх M4 , пока ваша ветка функций извлечена:

 git rebase -i M4
  

Вам будет представлен редактируемый фрагмент, похожий на следующий:

 pick 111111 F1
pick 222222 F2
pick 333333 F3
  

Затем вы отредактируете этот фрагмент, чтобы указать Git на squash F2 и F3 into F1 , в результате чего получится один коммит, который представляет все ваши изменения с момента разветвления:

 pick 111111 F1
squash 222222 F2
squash 222222 F3
  

F1 назначается как коммит для сквоша, потому что именно так работает команда (т. Е. Она объединяет изменения в предыдущий коммит).).

Сохраните эти изменения, выйдите из фрагмента, и вам будет представлен только один шаг разрешения конфликта.

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

Ответ №2:

Перебазирование — это применение коммитов поверх другого по одному за раз.

Из документации:

Затем коммиты […] повторно применяются к текущей ветке, один за другим, по порядку.

Итак, перебазирование эффективно объединяет одну фиксацию за раз поверх предыдущей. Теперь сравните и сравните с другим видом слияния, которое вы можете выполнить в Git:

 git checkout master
git merge feature
  

merge Команда делает именно то, о чем вы просите: она применяет совокупные изменения, связанные с последней фиксацией в feature ветке, поверх последней фиксации master в одной операции. Это означает, что вам придется решать все конфликты только один раз.

Операция слияния обычно приводит к созданию коммита слияния в целевой ветке; цель коммита слияния — объединить два (или более!) строки истории. Итак, в то время как обычная фиксация имеет только одного родителя, коммиты слияния, естественно, ссылаются на несколько родителей.

 M1 --- M2 --- M3 --- M4 --- MF
       |                    |
       M2 --- F1 --- F2 --- F3
  

Теперь операция слияния не обязательно должна приводить к фиксации слияния. Если вы хотите (и это, вероятно, то, что вы ищете), вы можете объединить изменения, которые произошли в разных ветвях, все еще создавая один единственный коммит.

Вы можете сделать это, создав так называемое слияние squash:

 git checkout master
git merge feature --squash
  

Разница здесь в том, что объединенные изменения из master и feature записываются в один коммит поверх master , в результате чего история выглядит следующим образом:

 M1 --- M2 --- M3 --- M4 --- MF
       |                    
       M2 --- F1 --- F2 --- F3
  

Где MF содержатся объединенные изменения из M4 и F3 со всеми разрешенными конфликтами.