git pull rebase origin master что это

Перебазирование

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

Простейшее перебазирование

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

В данном примере переключимся на ветку experiment и перебазируем её относительно ветки master следующим образом:

Это работает следующим образом: берётся общий родительский снимок двух веток (текущей, и той, поверх которой вы выполняете перебазирование), определяется дельта каждого коммита текущей ветки и сохраняется во временный файл, текущая ветка устанавливается на последний коммит ветки, поверх которой вы выполняете перебазирование, а затем по очереди применяются дельты из временных файлов.

После этого вы можете переключиться обратно на ветку master и выполнить слияние перемоткой.

Теперь снимок, на который указывает C4′ абсолютно такой же, как тот, на который указывал C5 в примере с трёхсторонним слиянием. Нет абсолютно никакой разницы в конечном результате между двумя показанными примерами, но перебазирование делает историю коммитов чище. Если вы взглянете на историю перебазированной ветки, то увидите, что она выглядит абсолютно линейной: будто все операции были выполнены последовательно, даже если изначально они совершались параллельно.

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

Более интересные перемещения

Теперь вы можете выполнить перемотку (fast-forward) для ветки master (см Перемотка ветки master для добавления изменений из ветки client ):

После чего вы сможете выполнить перемотку основной ветки ( master ):

Опасности перемещения

Но даже перебазирование, при всех своих достоинствах, не лишено недостатков, которые можно выразить одной строчкой:

Не перемещайте коммиты, уже отправленные в публичный репозиторий

Если вы будете придерживаться этого правила, всё будет хорошо. Если не будете, люди возненавидят вас, а ваши друзья и семья будут вас презирать.

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

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

Теперь кто-то другой внёс свои изменения, слил их и отправил на сервер. Вы стягиваете их к себе, включая новую удалённую ветку, что изменяет вашу историю следующим образом:

Если вы посмотрите git log в этот момент, вы увидите два коммита с одинаковыми авторами, датой и сообщением, что может сбить с толку. Помимо этого, если вы отправите свою историю на удалённый сервер в таком состоянии, вы вернёте все эти перебазированные коммиты на сервер, что ещё больше всех запутает. Логично предположить, что разработчик не хочет, чтобы C4 и C6 были в истории, и именно поэтому она перебазируется в первую очередь.

Меняя базу, меняй основание

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

Оказывается, что помимо контрольной суммы коммита SHA-1, Git также вычисляет контрольную сумму отдельно для патча, входящего в этот коммит. Это контрольная сумма называется «patch-id».

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

Определять, какая работа уникальна для вашей ветки (C2, C3, C4, C6, C7)

Определять, какие коммиты не были коммитами слияния (C2, C3, C4)

Определять, что не было перезаписано в основной ветке (только C2 и C3, поскольку C4 — это тот же патч, что и C4′)

Применять эти коммиты к ветке teamone/master

Это возможно, если C4 и C4′ фактически являются одним и тем же патчем, который был сделан вашим коллегой. В противном случае rebase не сможет определить дубликат и создаст ещё один патч, подобный C4 (который с большой вероятностью не удастся применить чисто, поскольку в нём уже присутствуют некоторые изменения).

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

Читайте также:  hettich с доводчиком clip on что это

Перемещение vs. Слияние

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

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

Противоположная точка зрения заключается в том, что история коммитов — это история того, как был сделан ваш проект. Вы не публикуете первый черновик книги или инструкции по поддержке вашего программного обеспечения, так как это нуждается в тщательном редактировании. Сторонники этого лагеря считают использование инструментов rebase и filter-branch способом рассказать историю проекта наилучшим образом для будущих читателей.

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

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

Источник

Команда Git Pull

Мы уже рассмотрели git merge, теперь перейдем к pull.

Команда pull забирает изменения из удаленного репозитория и интегрирует их с изменениями в локальном репозитории.

Пример использования

Чтобы забрать изменения из удаленной ветки dev репозитория origin и слить их с изменениями в текущей ветке, где мы находимся, выполним:

Это аналогично двум последовательным командам:

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

Параметры по умолчанию

Если попробовать выполнить pull без параметров, находясь в ветке master:

команда выполнится. Но с какой же веткой происходит в этом случае слияние? По умолчанию это ветка master репозитория origin. (При клонировании удаленного репозитория по умолчанию ему дается имя origin). То есть команда аналогична:

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

Настройка отслеживаемой ветки

Давайте сделаем так, чтобы, когда мы находимся в локальной ветке dev, по умолчанию слияние происходило с веткой dev репозитория origin. Перейдем в ветку dev и выполним команду:

Эта команда связало локальную ветку dev с удаленной веткой origin/dev.

Теперь когда мы находимся на локальной ветке dev и выполняем pull без параметров, слияние происходит по умолчанию с удаленной веткой dev:

То есть теперь вышеприведенная команда без параметров будет аналогична команде с параметрами:

git pull vs. git fetch

git fetch просто обновляет локальную копию удаленного репозитория. То есть все копии удаленных веток (которые записываются через слеш — например, origin/master) будут содержать самый последний коммит из удаленного репозитория.

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

Команда pull же состоит из fetch и merge. То есть помимо обновления копии удаленного репозитория на вашем компьютере, она еще и реально меняет содержимое папок, с которыми вы работаете. Вливает удаленную ветку в текущую.

git pull —rebase

Рассмотрим команду pull с параметром rebase:

На результат слияния параметр —rebase не влияет, единственное, что он делает — меняет вид истории коммитов.

До команды pull

Допустим, мы разветвились с удаленным репозиторием на коммите D:

До pull

Наши локальные коммиты с момента разветвления — это нижние E, F, G, а в удаленном репозитории с тех пор появились коммиты A, B, C. Нам надо их накатить сверху на наши коммиты E, F, G, что собственно и делает команда pull.

Обычный pull

Но тут возможны нюансы. По умолчанию делается дополнительный коммит H, который и включает все изменения из удаленной ветки:

git pull

pull —rebase

Если же мы выполним:

то история локальных коммитов будет выглядеть по другому (при том же результате слияния файлов):

git pull —rebase

При просмотре истории коммитов мы просто увидим ряд коммитов из основной ветки A, B, C, идущих за нашими локальными E, F, G. Кому-то такой вид выглядит чище, хотя разницы в итоговом содержимом файлов нет.

Читайте также:  какой ламинат под серые обои и белые двери

git pull force

Насильно выполнить git pull нельзя. Она не перезапишет локальные изменения, если есть конфликт. Конфликт все равно придется разрешать.

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

Далее, допустим надо перезаписать содержимое текущей ветки данными из ветки master репозитория origin:

Если надо перезаписать содержимое текущей ветки данными из другой ветки dev репозитория origin:

Но будьте внимательны с опцией —hard, она действительно затирает коммиты текущей ветки безвозвратно. Если надо их сохранить, то перед выполнением команды создайте новую ветку — в нее все сохранится:

Что еще интересно: коммиты reset —hard затирает, а если в папке были просто неотслеживаемые файлы, то они не будут затронуты.

Итоги

Команда pull — на любителя, потому что не всем нравится автоматически сливать ветки. Гораздно прозрачнее делать отдельно fetch и merge.

Источник

Git Rebase: руководство по использованию

Rebase — один из двух способов объединить изменения, сделанные в одной ветке, с другой веткой. Начинающие и даже опытные пользователи git иногда испытывают нежелание пользоваться ей, так как не видят смысла осваивать еще один способ объединять изменения, когда уже и так прекрасно владеют операцией merge. В этой статье я бы хотел подробно разобрать теорию и практику использования rebase.

Теория

Итак, освежим теоретические знания о том, что же такое rebase. Для начала вкратце — у вас есть две ветки — master и feature, обе локальные, feature была создана от master в состоянии A и содержит в себе коммиты C, D и E. В ветку master после отделения от нее ветки feature был сделан 1 коммит B.

После применения операции rebase master в ветке feature, дерево коммитов будет иметь вид:

Обратите внимание, что коммиты C’, D’ и E’ — не равны C, D и E, они имеют другие хеши, но изменения (дельты), которые они в себе несут, в идеале точно такие же. Отличие в коммитах обусловлено тем, что они имеют другую базу (в первом случае — A, во втором — B), отличия в дельтах, если они есть, обусловлены разрешением конфликтных ситуаций, возникших при rebase. Об этом чуть подробнее далее.

Такое состояние имеет одно важное преимущество перед первым, при слиянии ветки feature в master ветка может быть объединена по fast-forward, что исключает возникновение конфликтов при выполнении этой операции, кроме того, код в ветке feature более актуален, так как учитывает изменения сделанные в ветке master в коммите B.

Процесс rebase-а детально

Давайте теперь разберемся с механикой этого процесса, как именно дерево 1 превратилось в дерево 2?

Напомню, перед rebase вы находтесь в ветке feature, то есть ваш HEAD смотрит на указатель feature, который в свою очередь смотрит на коммит E. Идентификатор ветки master вы передаете в команду как аргумент:

Для начала git находит базовый коммит — общий родитель этих двух состояний. В данном случае это коммит A. Далее двигаясь в направлении вашего текущего HEAD git вычисляет разницу для каждой пары коммитов, на первом шаге между A и С, назовем ее ΔAC. Эта дельта применяется к текущему состоянию ветки master. Если при этом не возникает конфликтное состояние, создается коммит C’, таким образом C’ = B + ΔAC. Ветки master и feature при этом не смещаются, однако, HEAD перемещается на новый коммит (C’), приводя ваш репозитарий состояние «отделеной головы» (detached HEAD).

Успешно создав коммит C’, git переходит к переносу следующих изменений — ΔCD. Предположим, что при наложении этих изменний на коммит C’ возник конфликт. Процесс rebase останавливается (именно в этот момент, набрав git status вы можете обнаружить, что находитесь в состоянии detached HEAD). Изменения, внесенные ΔCD находятся в вашей рабочей копии и (кроме конфликтных) подготовлены к коммиту (пунктиром обозначена stage-зона):

Далее вы можете предпринять следующие шаги:

1. Отменить процесс rebase набрав в консоли

При этом маркер HEAD, будет перенесен обратно на ветку feature, а уже добавленные коммиты повиснут в воздухе (на них не будет указывать ни один указатель) и будут вскоре удалены.

При этом, если все конфликты действительно разрешены, будет создан коммит D’ и rebase перейдет к следующему, в данном примере последнему шагу.

После применения изменений ΔDE будет создан последний коммит E’, указатель ветки feature будет установлен на коммит E’, а HEAD станет показывать на ветку feature — теперь, вы находитесь в состоянии на втором рисунке, rebase окончен. Старые коммиты C, D и E вам больше не нужны.

При этом коммиты, созданные в процессе rebase-а, будут содержать данные как об оригинальном авторе и дате изменений (Author), так и о пользователе, сделавшем rebase (Commiter):

С небес на землю — rebase в реальных условиях

На самом деле обычно вы работаете не с двумя ветками, а с четырьмя в самом простом случае: master, origin/master, feature и origin/feature. При этом rebase возможен как между веткой и ее origin-ом, например feature и origin/feature, так и между локальными ветками feature и master.

Читайте также:  судебный приказ о взыскании алиментов на ребенка что делать

Rebase ветки с origin-ом

Если вы хотите начать работать с rebase, то лучше всего начать с ребейза своих изменений в ветке относительно ее копии в удаленном репозитарии. Дело в том, что когда вы добавляете коммит, и в удаленном репозитарии добавляется коммит, для объединения изменений по-умолчанию используется merge. Выглядит это примерно так:

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

Как поделиться веткой, к которой применен rebase, с коллегой

Тут все просто, наберите в консоли команду:

Force-режим просто копирует отсутствующие родительские коммиты ветки feature на origin и насильно устанавливает указатель ветки на тот же коммит, что и ваш локальный.

Будьте внимательны! Если вы забудете указать идентификатор ветки, то force-push будет выполнен для всех локальных веток, имеющих удаленный оригинал. При этом нужно понимать, что некоторые локальные ветки могут быть в неактуальном состоянии. То есть измененения, которые вы не успели затянуть будут удалены в origin-е. Конечно, сами коммиты не будут удалены — сбросятся только указатели ветки. Эта ситуация поправима — достаточно для каждой ветки найти человека, который последним пушил изменения в нее или уже успел их забрать. Он может сделать обычный push, вновь передав их на origin. Но вся эта морока вам ни к чему, так что лучше просто будьте внимательны.

Реинтеграция тематической ветки в master

Мы рассмотрели все необходимые операции для работы с ветками в стиле rebase. Осталось только переключиться в ветку master и сделать git merge feature. Ветка, подготовленная rebase-ом вольется в master по fast-forward, то есть указатель будет просто перемещен вперед.

В данном случае, на мой взгляд, merge-коммиты полезны и несут в себе информацию о моменте объединения веток. Этот граф выглядит как учебный пример, но такая структура вполне реальна при соблюдении некоторых простых правил всеми членами команды.

Заключение

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

В данной статье сделано одно допущение. Все это верно при простой модели ветвления — есть одна главная ветка master и несколько тематических, которые создаются от нее. Когда от тематической ветки создается другая тематическая ветка, есть свои нюансы при rebase-е первичной и вторичной ветки. О них можно прочитать в том самом официальном руководстве.

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

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

Источник

git pull

Использование git pull

Порядок действий

В этом сценарии команда git pull загрузит все изменения, начиная с того места, где разошлись локальная и главная ветки. В данном примере это точка E. Команда git pull получит удаленные коммиты из отходящей ветки (т. е. точки A‑B‑C). Затем в процессе запуска команды pull будет создан новый локальный коммит слияния, включающий содержимое новых удаленных коммитов из отходящей ветки.

На этой схеме видно, что при перебазировании с помощью команды pull не был создан новый коммит H. Вместо этого удаленные коммиты A‑B‑C были скопированы и добавлены в историю в локальной ветке origin/main перед локальными коммитами E–F–G с перезаписью последних.

Распространенные опции

Подобно вызову по умолчанию, извлекает удаленное содержимое, но не создает новый коммит со слитым содержимым.

Во время выполнения команды pull выдает подробный вывод о загружаемом содержимом и информацию о слиянии.

Обсуждение git pull

Сначала вы думаете, что ваш репозиторий синхронизирован, однако команда git fetch показывает, что с момента последней проверки версия origin ветки main была изменена. Затем команда git merge сразу интегрирует удаленную ветку main в локальную ветку.

Git pull и синхронизация

Команда git pull — одна из множества команд, отвечающих за синхронизацию удаленного содержимого. Команда git remote используется, чтобы указать, на каких удаленных конечных точках будут работать команды синхронизации. Команда git push используется для выгрузки содержимого в удаленный репозиторий.

Сравнение pull и rebase

Примеры использования git pull

В нижеприведенных примерах показано, как использовать команду git pull в общих сценариях.

Поведение по умолчанию

Команда git pull на удаленных ветках

Перебазирование с помощью git pull вместо слияния

В следующем примере показано, как выполнить синхронизацию с главной веткой main центрального репозитория, используя перебазирование.

В этом примере ваши локальные изменения просто помещаются поверх изменений всех остальных участников разработки.

Источник

Сказочный портал