Git rebase теряет историю, тогда зачем rebase? - PullRequest
46 голосов
/ 09 марта 2011

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

Ответы [ 4 ]

54 голосов
/ 09 марта 2011

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

  • Гений
  • Генерал
  • Компьютерный хакер

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

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

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

Гений

Он совершил 70 коммитов по 10 в день.

Общее

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

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

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

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

Вот история:

Гений

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

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

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

Общее

Общая мысль: Разделяй и властвуй!

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

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

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

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

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

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

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

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

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

27 голосов
/ 09 марта 2011

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

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

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

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

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

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

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

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

11 голосов
/ 09 марта 2011

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

Но rebase не ограничивается этим сценарием и в сочетании с "--interactive" позволяет локально переупорядочивать и очищать вашу историю. См. Также « Тримминг GIT Checkins / Squashing GIT History ».

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

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

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

git reset --hard [SHAnumber]

git rebase -f master

git push -f origin HEAD:master

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

git gc
...