Git rebase теряет историю, тогда зачем rebase?

Я искал перезагрузку с помощью Git за последние пару дней. Большинство аргументов для перезагрузки говорят, что он очищает историю и делает ее более линейной. Если вы выполняете простые слияния (например), вы получаете историю, которая показывает, когда история расходилась и когда она была возвращена вместе. Насколько я могу судить, rebasing удаляет всю эту историю. Вопрос в следующем: почему бы вам не хотеть, чтобы история репо отражала все способы разработки кода, в том числе, где и как оно расходилось?

Ответ 1

Насколько я могу судить, rebasing удаляет всю эту историю.

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

Особенно, когда вы работаете с другими людьми, каждый из которых работает над своими ветвями, требуя от некоторых изменений некоторых изменений (например, A просит B реализовать что-то, чтобы A мог использовать эту функцию в своей собственной разработке), это приводит к множеству слияний, Например, например:

     #--#--#--#--*-----*-----------------*---#---\         Branch B
    /           /     /                 /         \
---#-----#-----#-----#-----#-----#-----#-----#-----*       Branch A

В этом примере у нас есть ветвь, которая работает отдельно для времени, но постоянно втягивает изменения в исходную ветвь (# - оригинальные коммиты, * сливаются).

Теперь, если мы сделаем rebase на ветке B перед слиянием обратно, мы можем получить следующее:

                             #--#--#--#--#---\         Branch B
                            /                 \
---#---#---#---#---#---#---#---#---------------*       Branch A

Это представляет собой те же самые фактические изменения, но B был переустановлен на некоторую старшую фиксацию на A, поэтому все слияния на B, которые были сделаны ранее, больше не нужны (поскольку эти изменения уже существуют в этом более старом фиксации). И все коммиты, которые сейчас отсутствуют, представляют собой слияния, которые обычно не содержат никакой информации о процессе разработки. (Обратите внимание, что в этом примере вы также можете переустановить последнее коммит на A позже, чтобы получить прямую линию, эффективно удаляя любые подсказки ко второй ветке)

Ответ 2

Представьте, что вы работаете над секретным проектом мирового господства. В этом заговоре есть три вдохновителя:

  • The Genius
  • Общие
  • Компьютерный хакер

И все они соглашаются прийти на свою секретную базу в течение 1 недели каждый с одним подробным планом.

Компьютерный хакер, будучи прагматичным программистом, предложил использовать Git для хранения всех файлов планов. Каждый из них разветкит первоначальное репо проекта и объединит его через одну неделю.

Все согласны, и в следующие дни история звучит примерно так:

The Genius

Он делал в общей сложности 70 коммитов, 10 в день.

Общие

Он шпионил за репо своих товарищей и сделал стратегию победить их. Он сделал 3 фиксации, весь последний день.

Компьютерный хакер

Этот прагматичный программист использовал ветки. Он сделал 4 разных плана, каждый на ветке. Каждая ветвь была переустановлена, чтобы быть только одной фиксацией.

Прошло семь дней, и группа снова собралась, чтобы объединить все планы в один мастер. Все они очень хотели начать, поэтому все они пытались объединить все вещи самостоятельно.

Вот история:

The Genius

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

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

Итак, он закончил беспорядок, что даже гений не мог понять.

Общие

Общая мысль: Разделите и победите!

И поэтому он объединил репо гения на своем репо. Он посмотрел на журнал и увидел кучу коммитов из идеи Гения, которая следовала за непонятной прогрессией, до последнего дня. В последний день идеи генерала и гения были смешанными.

Он шпионил компьютер Hacker и знал о решении Rebase. Поэтому он сделал переложение своей собственной идеи и снова попытался слить.

Теперь журнал показал логическую прогрессию каждый день.

Компьютерный хакер

Этот прагматичный программист создал интеграционную ветвь для идеи Genius, другую для идеи General и другую для своих собственных идей. Он сделал перестановку в каждой ветке. И затем он объединил всех в мастера.

И все его товарищи по команде увидели, что его журнал великолепный. Это было просто. На первый взгляд это было непонятно.

Если идея ввела проблему, было ясно, в чём была введена фиксация, поскольку было только одно.

Они прекратили завоевывать весь мир, и они исчезли из-за использования Subversion.

И все были счастливы.

Ответ 3

Вы делаете rebase главным образом для того, чтобы переделать свои локальные коммиты (те, которые вы еще не нажали) поверх удаленной ветки (вы просто извлекаете), чтобы разрешить любой конфликт локально (т.е. прежде чем вы нажмете их обратно восходящее репо).
См. "git рабочий процесс и вопросы по перезагрузке и слиянию" и, довольно подробно: "git rebase vs git merge".

Но rebase не ограничивается этим сценарием и в сочетании с "--interactive", он позволяет выполнять локальный переупорядочивание и очистку вашей истории. См. Также "Обрезка git Проверки/Скриптинг git История".

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

  • В централизованной VCS важно никогда не терять историю, и она действительно должна отражать "все способы разработки кода".
  • В распределенной VCS, где вы можете делать всевозможные локальные эксперименты до публикации некоторых из ваших веток в восходящем направлении, это делает меньше смысл держать все в истории: не всем нужно клонировать и видеть все ваши ветки, тесты, альтернативы и т.д.

Ответ 4

Если вы допустили ошибку в публичном репозитории, и никто еще не разветкил/не слил/не вытащил из нее, вы можете сохранить лицо и путаницу:

git reset --hard [SHAnumber]

git rebase -f master

git push -f origin HEAD:master

Чтобы очистить корзину:

git gc