Команду git rebase часто считают колдовством Git, и новичкам следует держаться подальше от нее, но на самом деле она может упростить работу команд разработчиков. В этой статье мы сравниваем git rebase с родственной командой git merge.
концепция
Первое, что нужно понять, это то, что git rebase и git merge решают одну и ту же проблему. Обе команды предназначены для интеграции изменений из одной ветки в другую — просто делают они это по-разному.
Только представьте, что происходит, когда другой член команды обновляет основную ветку новым коммитом, когда вы начинаете разрабатывать новую функцию в выделенной ветке. Это вызывает историю форка для использованияGit как инструмент для совместной работыОно должно быть знакомо каждому.
Теперь давайте поговорим о том, когда новая фиксация в master связана с функцией, над которой вы работаете. Чтобы объединить новые коммиты в вашу ветку функций, у вас есть два варианта: слияние или перебазирование.
Merge
Самая простая — это ветка master в ветку feature:
git checkout feature
git merge master
В качестве альтернативы вы можете упростить до одной строки:
git merge master feature
Это создает новую «фиксацию слияния» в ветви функций, которая связывает истории двух ветвей вместе, создавая для вас структуру ветвей, которая выглядит следующим образом:
Слияние хорошо, потому что это неразрушающая операция. Существующая структура филиала не будет изменена никоим образом. Это позволяет избежать всех потенциальных ловушек перебазирования (обсуждаемых ниже).
С другой стороны, это также означает, что функцию необходимо объединять каждый раз, когда происходят изменения в восходящем направлении, и существуют несвязанные коммиты слияния. Если master меняется очень часто, это может серьезно загрязнить историю вашей ветки. Хотя влияние этой проблемы можно смягчить с помощью расширенных параметров журнала git, другим разработчикам может быть сложно понять историю изменений проекта.
Rebase
В качестве альтернативы слиянию вы можете перебазировать функциональную ветку в главную ветку с помощью следующей команды:
git checkout feature
git rebase master
Это переместит всю ветку Feature в верхнюю часть ветки Master, которая эффективно интегрирует новую отправку всех MASTER. Однако rebase не использует Merge Commit, а переписывает историю проекта, создавая новую отправку для каждой отправки в исходной ветке.
Основным преимуществом rebase является более чистая история проекта. Во-первых, он устраняет ненужные коммиты слияния из git merge. Во-вторых, как вы можете видеть на изображении выше, rebase также создает совершенно линейную историю проекта — вы можете проследить от вершины функциональной ветви до начала проекта без каких-либо ответвлений. Это упрощает навигацию по проекту, чем команды git log, git bisect и gitk.
Однако у этой необработанной истории коммитов есть два компромисса: безопасность и отслеживаемость. Переписывание истории проекта может иметь катастрофические последствия для вашего совместного рабочего процесса, если вы не будете следовать золотому правилу перебазирования. Во-вторых, rebase теряет контекст, предоставленный фиксацией слияния, — вы не можете видеть, когда восходящие изменения объединяются в функцию.
Interactive Rebase
Интерактивная перебазировка дает вам возможность изменять коммиты при перемещении их в новую ветку. Это более эффективно, чем автоматическая перебазировка, поскольку обеспечивает полный контроль над историей коммитов ветки. Обычно это используется для очистки беспорядочной истории перед слиянием функциональной ветки с основной веткой.
Чтобы начать интерактивный сеанс, передайте параметр i команде git rebase:
git checkout feature
git rebase -i master
Это откроет текстовый редактор со списком всех коммитов, которые собираются переместить:
pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3
Список дает точное представление о ветке после выполнения перебазирования. Изменяя команду выбора и/или изменяя порядок, вы можете сделать историю ветки такой, какой хотите. Например, если вторая фиксация устраняет небольшую проблему в первой фиксации, вы можете объединить их в одну фиксацию с помощью следующей команды fixup:
pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3
Когда вы сохраните и закроете файл, Git rebase будет выполнен в соответствии с вашими инструкциями, в результате чего история проекта будет выглядеть следующим образом:
Устранение этого бессмысленного представления делает вашу историю более читабельной. Это то, что git merge не может сделать.
Золотое правило перебазирования
Как только вы поймете, что такое rebase, самое главное — понять, когда его не следует использовать. Золотое правило git rebase — никогда не использовать его в публичной ветке.
Например, рассмотрим, что произойдет, если вы перебазируете ветку master в ветку feature:
rebase перемещает все коммиты из master в начало фичи. Проблема в том, что это происходит только в вашем репо. Все остальные разработчики по-прежнему используют оригинальную мастер-версию. Поскольку перебазирование приводит к совершенно новой фиксации, Git будет думать, что история вашей основной ветки отличается от истории всех остальных.
Единственный способ синхронизировать две основные ветки — это объединить их вместе, в результате чего получится дополнительный коммит слияния и два набора коммитов, содержащих одни и те же изменения (исходный коммит и изменения из ветки перебазирования). Это была бы очень запутанная ситуация.
Поэтому, прежде чем запускать git rebase, всегда спрашивайте себя: «Кто-нибудь еще использует эту ветку?» Если ответ «да», то уберите руки с клавиатуры и рассмотрите возможность использования неразрушающего метода (например, команды git revert) . В противном случае вы можете переписать историю как хотите.
Принудительный толчок
Если вы попытаетесь отправить основную ветку перебазирования в удаленный репозиторий, Git не позволит вам сделать это, поскольку она конфликтует с удаленной основной веткой. Однако вы можете форсировать отправку, передав флаг --force следующим образом:
#这个命令要非常小心!
git push --force
Это перезапишет удаленную ветку master, чтобы она соответствовала ветке rebase, и запутает остальную часть команды. Поэтому используйте эту команду очень осторожно, только если вы точно знаете, что делаете.
Рабочий процесс
rebase может быть интегрирован в ваш существующий в той мере, в какой это необходимо вашей команде.Git рабочий процесссередина. В этом разделе мы посмотрим на преимущества ребазы на различных этапах развития функций.
Первым шагом в любом рабочем процессе git rebase является создание выделенных веток для каждой функции. Это дает вам необходимую структуру ветвления для безопасного использования перебазирования:
локальная уборка
добавить ребазпроцесс работыОдин из лучших способов сделать это — очистить локальные незавершенные функции. Регулярно выполняя интерактивные перебазирования, вы можете гарантировать, что каждая фиксация в вашей функции актуальна и значима. Это позволяет вам писать код, не беспокоясь о том, чтобы разбить его на изолированные коммиты — вы можете исправить это постфактум.
При вызове git rebase есть два основных варианта: родительская ветвь функции (например, master) или исторические коммиты в функции. Мы видели пример первого варианта в разделе Interactive Rebasing. Последний вариант подходит, когда вам нужно исправить только несколько последних коммитов. Например, следующая команда предназначена только для интерактивной перебазировки последних 3 коммитов.
git checkout feature
git rebase -i HEAD~3
Указав HEAD~3 в качестве новой базы, вы на самом деле не перемещаете ветку — вы просто интерактивно переписываете 3 коммита после нее. Обратите внимание, что это не приведет к объединению восходящих изменений в ветку функций.
Если вы хотите переписать всю функцию, используя этот метод, можно использовать команду git merge-base, чтобы найти исходную базу ветки функции. Следующее возвращает исходный идентификатор фиксации базы, который затем можно передать в git rebase:
git merge-base feature master
Использование интерактивной перебазировки — отличный способ представить рабочий процесс git rebase, поскольку он влияет только на локальные ветки. Единственное, что могут видеть другие разработчики, — это ваш готовый продукт, который должен представлять собой краткую и понятную историю веток.
Но опять же, это относится только к веткам частных функций. Если вы сотрудничаете с другими разработчиками в одной и той же ветке, ветка становится общедоступной, и вы можете переписать ее историю.
Объединить исходные изменения в функцию
В разделе «Концепции» мы увидели, как ветки функций могут объединять вышестоящие изменения от мастера с помощью git merge или git rebase. Слияние — это безопасный вариант, который сохраняет всю историю репозитория, в то время как rebase создает линейную историю, перемещая ветки функций на вершину мастера.
Это использование git rebase похоже на локальную очистку (и может выполняться одновременно), но в процессе оно включает в себя те коммиты выше по течению от мастера.
Помните, перебазируйте в удаленную ветку, а не в главную. Это происходит при сотрудничестве с другим разработчиком над той же функциональностью, и вам нужно объединить их изменения в свой репозиторий.
Например, если вы и другой разработчик по имени Джон добавили новую фиксацию в ветку функций, после извлечения удаленной ветки из репозитория Джона ваш репозиторий может выглядеть так:
Вы можете обойти эту ветку так же, как вы интегрировали вышестоящие изменения из мастера: либо объединить локальную функцию с john/feature, либо перебазировать локальную функцию в john/feature.
Обратите внимание, что эта перебазировка не нарушает золотое правило, так как перемещаются только ваши локальные фичи — все, что было до этого, не будет затронуто. Это как «добавить мои изменения к тому, что уже сделал Джон» В большинстве случаев это более интуитивно понятно, чем синхронизация с удаленной веткой через слияние.
По умолчанию команда git pull выполняет слияние, но вы можете принудительно интегрировать ее с перебазированием удаленной ветки, передав ей параметр --rebase.
Интегрируйте проверенные функции
После того, как ваша команда передала функцию, вы можете перебазировать ее в верхнюю часть основной ветки, а затем git объединить функцию с основной кодовой базой.
Это аналогичная ситуация, когда изменения объединяются вверх по течению с веткой функций, но поскольку вам не разрешено переписывать отправленные в основной ветке, поэтому вам придется в конечном итоге использовать git merge функций интеграции. Однако, выполнив ребаз перед слиянием, вы можете убедиться, что история слияния идеально линейна. Это также дает вам возможность сжать любые последующие запросы, отправленные во время добавленного извлечения.
Если вы не знакомы с git rebase, вы всегда можете выполнить rebase во временной ветке. Таким образом, если вы случайно испортите историю функции, вы сможете просмотреть исходную ветку и повторить попытку. Например:
git checkout feature
git checkout -b temporary-branch
git rebase -i master
#[清理历史]
git checkout master
git merge temporary-branch
Суммировать
Вот что вам нужно знать о перебазировании вашей ветки. Если вы предпочитаете чистую, линейную историю коммитов, исключающую ненужные слияния, вам следует использовать git rebase вместо git merge при наследовании изменений из другой ветки.
С другой стороны, если вы хотите сохранить полную историю проекта и избежать риска перезаписи публичных коммитов, вы все равно можете использовать git merge. Оба варианта прекрасны, но, по крайней мере, возможность использовать git rebase имеет свои преимущества.
Нажмите на оригинальную английскую ссылку
Для получения дополнительных статей, пожалуйста, посетите: http://www.apexyun.com
Общедоступный номер: Galaxy № 1
Контактный адрес электронной почты: public@space-explore.com
(Пожалуйста, не перепечатывайте без разрешения)