Разное

Git master merge: 35. Слияние в ветку master

Содержание

Сравнение слияния и перебазирования | Atlassian Git Tutorial

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

Обзор основных моментов

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

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

А теперь предположим, что новые коммиты в главной ветке затрагивают функционал, над которым вы работаете. Для включения новых коммитов в свою функциональную ветку можно использовать два варианта: merge или rebase.

Способ слияния (merge)

Проще всего слияние ветки master с функциональной веткой выполняется с помощью следующей команды:

git checkout feature
git merge master

При желании этот код можно записать в одну строку:

git merge feature master

Эта операция создает в ветке feature новый «коммит слияния», связывающий истории обеих веток. Структура веток будет выглядеть так:

Слияние (merge) — это отличная неразрушающая операция. Существующие ветки никак не изменяются. Эта операция позволяет избегать потенциальных проблем, связанных с выполнением команды rebase (и описанных ниже).

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

Способ перебазирования (rebase)

Вместо слияния можно выполнить перебазирование функциональной ветки (feature) на основную (master) с помощью следующих команд:

git checkout feature
git rebase master

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

Главное преимущество rebase — более чистая история проекта. Во-первых, эта команда устраняет ненужные коммиты слияния, необходимые для git merge. Во-вторых, как показано на рисунке выше, команда rebase создает идеальную линейную историю проекта — вы сможете отследить функционал до самого начала проекта без каких-либо форков. Это упрощает навигацию в проекте с помощью таких команд, как git log, git bisect и gitk.

Однако такая безупречная история коммитов требует определенных жертв: жертвовать приходится безопасностью и отслеживаемостью. Если не следовать Золотому правилу Rebase, перезапись истории проекта может обернуться катастрофическими последствиями для совместных рабочих процессов. Кроме того, при выполнении rebase теряется контекст, доступный в коммите со слиянием: вы не сможете увидеть, когда вышестоящие изменения были включены в функционал.

Интерактивное перебазирование

Интерактивная операция rebase позволяет изменять коммиты при их перемещении в новую ветку. Этот вариант предоставляет еще больше возможностей, чем автоматическое выполнение 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

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

pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

Когда вы сохраните и закроете файл, Git выполнит перебазирование в соответствии с вашими указаниями. История проекта затем примет следующий вид:

Удаление незначительных коммитов помогает быстрее разобраться в истории функциональной ветки. Команда git merge просто не в состоянии этого сделать.

Золотое правило перебазирования

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

К примеру, представьте, что произойдет, если вы выполните rebase главной ветки в свою функциональную ветку.

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

Единственный способ синхронизировать две главные ветки — выполнить их обратное слияние. Это приведет к дополнительному коммиту слияния и двум наборам коммитов, которые содержат одни и те же изменения (исходные изменения и изменения из вашей ветки после rebase). Нужно ли говорить, что ситуация получится крайне запутанная?

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

Принудительная отправка изменений

Git заблокирует попытку поместить измененную главную ветку обратно в удаленный репозиторий, поскольку она вступит в конфликт с удаленной главной веткой. Но эту операцию можно форсировать, добавив флаг --force:

# Будьте крайне осторожны с этой командой! git push --force

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

Одна из немногих ситуаций, требующих форсированного помещения кода, — это локальная очистка после помещения частной функциональной ветки в удаленный репозиторий (например, для создания резервной копии). Это равноценно заявлению: «Ой, я ведь не хотел отправлять исходную версию этой функциональной ветки. Лучше возьмите текущую версию». Здесь также важно, чтобы никто после коммитов не начал работу из исходной версии функциональной ветки.

Пошаговый разбор процесса

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

В любом рабочем процессе с применением команды git rebase сначала нужно создать отдельную ветку для каждой функции. Полученная структура веток необходима для безопасного перебазирования:

Локальная очистка

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

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

git checkout feature git rebase -i HEAD~3

Указав HEAD~3 в качестве нового положения, вы не перемещаете ветку как таковую, а лишь интерактивно переписываете 3 последующих коммита. Следует отметить, что при этой операции вышестоящие изменения не включаются в функциональную ветку.

Если с помощью этого способа вы хотите переписать всю функциональную ветку, найти начальное положение функциональной ветки поможет команда git merge-base. Следующая команда возвращает ID коммита начального положения, который затем можно передать в команду git rebase:

git merge-base feature master

Такое использование интерактивной операции rebase отлично поможет включить git rebase в рабочий процесс, поскольку затронет только локальные ветки. Другие разработчики увидят только законченную версию с простой и отслеживаемой историей функциональной ветки.

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

Варианта очистки локальных коммитов с интерактивным использованием rebase с помощью команды git merge не существует.

Включение восходящих изменений в функциональную ветку

В разделе «Обзор основных моментов» рассматривалось включение вышестоящих изменений из ветки master в функциональную ветку с помощью команды git merge или git rebase. Операцию слияния можно выполнять безопасно, поскольку при этом сохраняется вся история репозитория. При выполнении перебазирования создается линейная структура: функциональная ветка перемещается в конец ветки master.

В этом случае команда git rebase используется так же, как и локальная очистка (которую можно осуществить одновременно), но при ее выполнении включаются вышестоящие изменения из ветки master.

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

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

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

Обратите внимание: такое перебазирование не нарушает «золотое правило», поскольку перемещаются только коммиты вашей ветки feature, тогда как предшествующие элементы остаются нетронутыми. В сущности, эта операция позволяет лишь добавить ваши изменения к наработкам Джона. Чаще всего это проще, чем выполнять синхронизацию с удаленной веткой посредством коммита слияния.

По умолчанию команда git pull выполняет слияние. Однако если передать ей параметр --rebase, будет выполнено перебазирование для удаленной ветки.

Проверка функции с помощью запроса pull

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

Все изменения, сделанные другими разработчиками, нужно добавлять командой git merge, а не git rebase.

Поэтому хорошей идеей является очистка кода с помощью интерактивной операции rebase перед созданием пул-реквеста.

Внедрение утвержденной функции

После одобрения функциональной ветки коллегой вы можете выполнить ее rebase в конец главной, а затем использовать команду git merge для включения функциональной ветки в основную базу кода.

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

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

git checkout feature
git checkout -b temporary-branch
git rebase -i master
# [Clean up the history]
git checkout master
git merge temporary-branch

Резюме

Теперь у вас достаточно информации, чтобы начать использовать rebase для своих веток. Если вы предпочитаете иметь чистую линейную историю без ненужных коммитов слияния, используйте команду git rebase вместо git merge при включении изменений из другой ветки.

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

Зачем мне «master» в git merge origin/master?

Соглашение при использовании git и вы хотите получить изменения от сервера:

git fetch

git merge origin/master

Я знаю, что есть также git pull, но мой конкретный вопрос касается синтаксиса origin/master . Что делает часть master ? Если я просто делаю git merge origin (без master), это, кажется, работает. Я знаю, что master -это ветвь, но если я отслеживаю более одной ветви пульта дистанционного управления, будет ли нормальным вариантом использования merge для всех них?

git

merge

branch

git-merge

branching-and-merging

Поделиться

Источник


Marc Stober    

26 февраля 2014 в 21:22

2 ответа


  • Что такое origin/master в git по сравнению с origin master?

    Я хотел добавить этот вопрос в качестве комментария к ответу @KevinBallard здесь What’s разница «origin master» против «origin/master» , но мой комментарий был слишком длинным. Поэтому мой вопрос таков: Если я нахожусь в ветке под названием topic , можно ли просто написать…

  • Проблема с git pull master не синхронизирована с origin master

    Вот последовательность шагов, которые я выполнил: совершил мои изменения в отрасли, чтобы местный мастер (идентификатор фиксации(коммита) dc9afg2k ) git fetch origin master && git merge origin master git checkout master git pull (это вытянуло все последние изменения) git fetch origin. ..



4

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

Поделиться


mipadi    

26 февраля 2014 в 22:03



4

Аргумент(ы) к merge разрешен для фиксации(коммита)-IDs. Это означает, что правила в gitrevisions применяются. В общем, origin/name решает один из «remote branchs», что git fetch и git push держат up-to-date на каждом fetch-and-push.

«Удаленная ветвь», также называемая «ветвью удаленного отслеживания», — это просто ветвеподобная метка, чей «full name» начинается с refs/remotes/ . Все те, что для пульта дистанционного управления с именем origin , находятся в refs/remotes/origin/ . При нормальной работе git fetch обращается к какому-нибудь удаленному (например, origin ) репозиторию git и спрашивает его: «Эй, какие у вас там ветви и каковы их значения SHA-1?» Когда он получает ответы, он хранит их локально, в вашем хранилище git: refs/remotes/origin/master , refs/remotes/origin/devel и так далее. Так что это позволяет вам узнать, как все выглядело «там», когда ваш git в последний раз имел возможность синхронизироваться.

Их не следует путать с тем, что git называет «tracking branches» (или «local tracking branches»). Local branches are labels whose «full name» начинается с refs/heads/ . Они считаются «tracking», если с ними связана «upstream» информация. Вы можете получить восходящую информацию при первом создании ветви—обычно это происходит для локальных ветвей с именами «same» в качестве удаленных ветвей, например master против origin/master, — или вы можете установить (или изменить) ее позже с помощью git branch --set-upstream-to .

Все они отличаются от синтаксиса git pull : git pull origin master довольно отличается и намного старше, полностью предшествуя идее «remote-tracking branches». 1 такое случайное сходство, как мне кажется, является источником большой путаницы (я знаю, что много лет назад это сбивало меня с толку).


1 в частности, вы использовали (и все еще можете) git pull из имени URL, а не «remote». Это пошло (и все еще идет) в другой репозиторий git, как обычно, и получает список, по крайней мере, некоторых его ветвей (иногда только тех, которые представляют интерес). Но поскольку это его ветви, а не ваши, они записываются в файл под названием FETCH_HEAD . Таким образом, в этот момент он принесет master из «там», но поместит его в FETCH_HEAD , а не в ветвь удаленного отслеживания-с необработанным URL у вас нет удаленного имени, поэтому нет никакого способа назвать ветвь удаленного отслеживания: нет origin , с помощью которого можно построить префикс refs/remotes/origin . Аргумент master для git-pull тогда означает: «идите искать через FETCH_HEAD , чтобы найти их ветвь master

Поделиться


torek    

26 февраля 2014 в 23:39


Похожие вопросы:

что делает git merge origin/master?

После извлечения с пульта дистанционного управления с помощью git fetch нам нужно использовать что-то вроде git merge origin/master Я хотел бы знать, делает ли эта команда git commit одновременно?…

git pull origin master не обновляет origin/master?

Согласно документации, git pull выполняет git fetch , а затем git merge, однако в этом случае выполнение git pull origin master должно выполнять git fetch origin master , верно? Однако, по-видимому,…

Есть ли какая-то разница между «git merge origin master» и » git merge origin/master`?

Может ли кто-нибудь объяснить разницу между git merge origin master и git merge origin/master ? Я случайно сделал git merge origin master . Если это не так, то какова команда для сброса этого…

Что такое origin/master в git по сравнению с origin master?

Я хотел добавить этот вопрос в качестве комментария к ответу @KevinBallard здесь What’s разница «origin master» против «origin/master» , но мой комментарий был слишком…

Проблема с git pull master не синхронизирована с origin master

Вот последовательность шагов, которые я выполнил: совершил мои изменения в отрасли, чтобы местный мастер (идентификатор фиксации(коммита) dc9afg2k ) git fetch origin master && git merge…

разница между git merge origin/master и git pull

Я работаю над местным веткой BDD-local и хотел бы получить изменения от других разработчиков. Другие разработчики используют свою собственную ветвь, и как только они довольны модульными тестами, они…

Разница между git merge Мастер и origin/master?

Результат выполнения команды git merge origin/master : javanoob@DELL:~/workspace/PROJECT_One$ git merge origin/master Updating d83ef9c. .dd520ea error: The following untracked working tree files…

git merge origin master не работает

git status Он получит: On branch master Your branch is behind ‘origin/master’ by 1 commit, and can be fast-forwarded. (use git pull to update your local branch) nothing to commit, working tree clean…

В чем разница между «git merge origin/master»» и «git merge master»

У меня была проблема, когда я пытался синхронизировать свою ветвь разработки с мастером , и теперь я пытаюсь понять, что произошло. Главная проблема заключалась в том, что я попробовал две вещи , и…

Как синхронизировать git master, origin/master и upstream master

На приведенной выше фотографии показано, где сейчас находится master и его 2 удаленные ветви слежения. Нет никакой разницы в изменении кода между remotes/upstream/master и другими 2 ветвями. Как мне…

Git: Опции слияния для команд merge и pull

В Git для команд merge и pull можно использовать опции, определяющие стратегию слияния изменений.

Основная опция -s <стратегия> определяет стратегию слияния. Возможные значения:

  • resolve
  • recursive
  • octopus
  • ours
  • subtree

Так же есть уточняющая опция -X<механизм>, которая принимает значения:

  • ours
  • theirs
  • subtree[=path]

Следует обратить внимание, что есть и стратегия с именем ours, и механизм с именем ours, и это разные вещи!

Выдержка из документации:

The merge mechanism (git-merge and git-pull commands) allows the

backend merge strategies to be chosen with -s option. Some strategies

can also take their own options, which can be passed by giving

-X<option> arguments to git-merge and/or git-pull.

resolve

This can only resolve two heads (i.e. the current branch and

another branch you pulled from) using a 3-way merge algorithm. It

tries to carefully detect criss-cross merge ambiguities and is

considered generally safe and fast.

recursive

This can only resolve two heads using a 3-way merge algorithm. When

there is more than one common ancestor that can be used for 3-way

merge, it creates a merged tree of the common ancestors and uses

that as the reference tree for the 3-way merge. This has been

reported to result in fewer merge conflicts without causing

mis-merges by tests done on actual merge commits taken from Linux

2.6 kernel development history. Additionally this can detect and

handle merges involving renames. This is the default merge strategy

when pulling or merging one branch.

The recursive strategy can take the following options:

ours

This option forces conflicting hunks to be auto-resolved

cleanly by favoring our version. Changes from the other tree

that do not conflict with our side are reflected to the merge

result.

This should not be confused with the ours merge strategy, which

does not even look at what the other tree contains at all. It

discards everything the other tree did, declaring our history

contains all that happened in it.

theirs

This is opposite of ours.

subtree[=path]

This option is a more advanced form of subtree strategy, where

the strategy makes a guess on how two trees must be shifted to

match with each other when merging. Instead, the specified path

is prefixed (or stripped from the beginning) to make the shape

of two trees to match.

octopus

This resolves cases with more than two heads, but refuses to do a

complex merge that needs manual resolution. It is primarily meant

to be used for bundling topic branch heads together. This is the

default merge strategy when pulling or merging more than one

branch.

ours

This resolves any number of heads, but the resulting tree of the

merge is always that of the current branch head, effectively

ignoring all changes from all other branches. It is meant to be

used to supersede old development history of side branches. Note

that this is different from the -Xours option to the recursive

merge strategy.

subtree

This is a modified recursive strategy. When merging trees A and B,

if B corresponds to a subtree of A, B is first adjusted to match

the tree structure of A, instead of reading the trees at the same

level. This adjustment is also done to the common ancestor tree.

Подробнее о стратегиях слияния (на русском) тут:

http://habrahabr.ru/post/195674/

Стратегия resolve

Стратегия resolve — классическое трехсторонее слияние (three-way merge). Стандартный алгоритм трехстороннего слияния применяется для двух файлов с общим предком. Условно этот алгоритм можно представить в виде следующих шагов:

  1. поиск общего предка,
  2. поиск блоков, изменившихся в обеих версиях относительно общего предка,
  3. записываются блоки, оставшиеся без изменения,
  4. блоки, изменившиеся только в одном из потомков, записываются как измененные,
  5. блоки, изменившиеся в обеих версиях, записываются только если изменения идентичны, в ином случае объявляется конфликт, разрешение которого предоставляется пользователю.

Эта стратегия имеет один недостаток: в качестве общего предка двух веток всегда выбирается наиболее ранний общий коммит. Для случая из нашего первого примера это не страшно, можно смело применять git merge feature -s resolve, и результат будет ожидаемым:

master: A — B — C — D — (M)

\ /

feature: X — Y

Здесь C — общий коммит двух веток, дерево файлов, соответствующее этому коммиту, принимается за общего предка. Анализируются изменения, произведенные в ветках master и feature со времен этого коммита, после чего для коммита (M) создается новая версия дерева файлов в соответствии с пунктами 4 и 5 нашего условного алгоритма.

В каком же случае проявляется недостаток стратегии resolve? Он проявляется в том случае, если для коммита (M) нам пришлось разрешить конфликты, после чего мы продолжили разработку и еще раз хотим выполнить git merge feature -s resolve. В этом случае в качестве общего предка снова будет использован коммит C, и конфликты произойдут снова и будут нуждаться в нашем вмешательстве.

Стратегия recursive

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

  1. проводится поиск всех кандидатов на общего предка,
  2. по цепочке проводится слияние кандидатов, в результате чего появляется новый «виртуальный» предок, причем более свежие коммиты имеют более высокий приоритет, что позволяет избежать повторного проявления конфликтов.

Результат этого действия принимается за общего предка и проводится трехсторонее слияние.

Для иллюстрации этой стратегии позаимствуем пример из статьи Merge recursive strategy из блога «The plasticscm blog»:

Итак, у нас есть две ветки: main и task001. И так вышло, что наши разработчики знают толк в извращениях: они слили коммит 15 из ветки main с коммитом 12 из ветки task001, а так же коммит 16 с коммитом 11. Когда нам понадобилось слить ветки, оказалось, что поиск реального предка — дело неблагодарное, но стратегия recursive с ее конструированием «виртуального» предка нам поможет. В результате мы получим следующую картину:

Стратегия recursive имеет множество опций, которые передаются команде git-merge с помощью ключа -X:

  • ours и theirs
    Используются для автоматического разрешения конфликтов. Ours — предпочитать «нашу» версию, версию «dst», theirs — предпочитать «их» версию.
  • renormalize (no-renormalize)
    Предотвращает ложные конфликты при слиянии вариантов с разными типами перевода строк.
  • diff-algorithm=[patience|minimal|histogram|myers], а так же опция patience
    Выбор алгоритма дифференциации файлов.
    Дополнительную информацию об этих опциях можно найти в документации по git-diff. Если кратко, свойства этих алгоритмов следующие:
    default, myers — стандартный, жадный алгоритм. Он используется по умолчанию.
    minimal — производится поиск минимальнейших изменений, что занимает дополнительное время.
    patience — использовать алгоритм «patience diff». О нем можно почитать у автора алгоритма, либо в сокращенном варианте на SO.
    histogram — расширяет алгоритм patience с целью, описанной как «support low-occurrence common elements». Сказать честно, я не смог найти достаточно ясного ответа на вопрос, какие конкретно случаи подразумеваются и буду очень рад, если кто-нибудь поможет найти этот ответ.
  • ignore-space-change, ignore-all-space, ignore-space-at-eol
    Корни этих опций лежат, опять же, в git-diff и относятся к дифференциации файлов при слиянии.
    ignore-space-change — игнорируются различия в количестве пробелов, идущих подряд, а так же пробелы в конце строки,
    ignore-all-space — пробелы абсолютно игнорируются при сравнении,
    ignore-space-at-eol — игнорируются различия в пробелах в конце строки.
  • rename-threshold=<n>
    Данная опция задает порог, по достижении которого файл может считаться не новым, а переименованным файлом, которого git-diff не досчитался. Например, -Xrename-threshold=90% подразумевает, что переименованным считается файл, который содержит от 90% контента некоторого удаленного файла.
  • subtree[=<path>]
    Выполнение рекурсивного слияния с этой опцией будет более продвинутым вариантом стратегии subtree, где алгоритм основывается на предположении, как деревья должны совместиться при слиянии. Вместо этого в этом случае указывается конкретный вариант.

Стратегия octopus

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

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

Стратегия ours

Не следует путать стратегию ours и опцию ours стратегии recursive.

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

$ git checkout obsolete

$ git merge -s recursive -Xtheirs master

Стратегия ours — более радикальное средство.

Стратегия subtree

Для иллюстрации данной стратегии возьмем пример из главы Слияние поддеревьев книги «Pro Git».

Добавим в наш проект новые удаленный репозиторий, rack:

$ git remote add rack_remote [email protected]:schacon/rack.git

$ git fetch rack_remote

warning: no common commits

remote: Counting objects: 3184, done.

remote: Compressing objects: 100% (1465/1465), done.

remote: Total 3184 (delta 1952), reused 2770 (delta 1675)

Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.

Resolving deltas: 100% (1952/1952), done.

From [email protected]:schacon/rack

* [new branch] build -> rack_remote/build

* [new branch] master -> rack_remote/master

* [new branch] rack-0.4 -> rack_remote/rack-0.4

* [new branch] rack-0.9 -> rack_remote/rack-0.9

$ git checkout -b rack_branch rack_remote/master

Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.

Switched to a new branch «rack_branch»

Ясно, что ветки master и rack_branch имеют абсолютно разные рабочие каталоги. Добавим файлы из rack_branch в master с использованием squash, чтобы избежать засорения истории ненужными нам фактами:

$ git checkout master

$ git merge —squash -s subtree —no-commit rack_branch

Squash commit — not updating HEAD

Automatic merge went well; stopped before committing as requested

Теперь файлы проекта rack у нас в рабочем каталоге.

Как обновить свою ветку последними изменениями с основной ветки

Обычно, когда разрабатывается какой-то функционал, создается отдельная ветка, которая ответвляется от основной линии разработки — master или develop (мы будем использовать master). Однако, чем дольше мы работаем над своей веткой, тем больше будет окончательное слияние (merge).

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

Хорошей практикой является создание отдельной ветки для разработки наших новых функциональностей или даже обратных исправлений. Тем не менее, настоятельно рекомендуется синхронизировать её с основной линией разработки, которая может быть master или с какой-либо отдельной веткой, как можно чаще.

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

Для обновления своего кода, прежде всего, нужно стянуть все изменения. Нам нужно убедиться, что мы синхронизированы и обновлены. Будучи на основной ветке master, делаем:

Затем переходим на нашу ветку разработки. Теперь для синхронизации с веткой master у нас есть разные возможности.

Настоятельно рекомендуется так делать, если это общая ветка. Если мы пушнем данные изменения в удаленный репозиторий origin/master, то другие разработчики тоже смогут работать над этим же кодом.

Однако, если эта ветка только наша и над ней работаем только мы, тогда можно использовать команду git rebase: возьмёт каждый коммит из master и объединит их поверх коммитов в нашей ветке.

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

Давай выполним rebase.
Будучи на ветке разработки делаем git rebase с master.

Что он делает? — перематывает HEAD и заменяет нашу работу поверх master:

First, rewinding head to replay your work on top of it...
Applying:

Теперь наши коммиты содержат все последние изменения, произошедшие в master.

Git: объединить ветку с мастером

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

В устаревших системах контроля версий (таких как CVS) сложность слияния ограничивалась только опытными пользователями.Другие современные, но централизованные системы контроля версий, такие как Subversion, требуют, чтобы коммиты выполнялись в центральном репозитории, поэтому гибкий рабочий процесс с локальным ветвлением и слиянием нетипичен.

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

Команда git branch используется для вывода списка всех существующих веток в репозитории. Звездочка появится рядом с активной в данный момент веткой.

  $ ветка git
* владелец
  

Чтобы создать новую ветку, мы можем использовать команду git branch new-branch . Это создаст новую ветку, отражающую коммиты текущей активной ветки.

  $ git branch новая ветка
$ git ветка
* владелец
новая ветка
  

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

На этом этапе мы создали новую ветку, но по-прежнему находимся в исходной ветке. Чтобы начать работу над новой веткой, нам сначала нужно запустить команду git checkout new-branch . Это изменит активную ветвь на новую ветку.

  $ git checkout новая ветка
Перешел на ветку «новая ветка»
$ git ветка
владелец
* новая ветка
  

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

Сначала мы запускаем git checkout master , чтобы изменить активную ветвь обратно на master. Затем мы запускаем команду git merge new-branch , чтобы объединить новую функцию с основной веткой.Обратите внимание, что git merge объединяет указанную ветку в текущую активную ветвь. Итак, нам нужно быть в ветке, которую мы соединяем с и .

  # ... разработать код ...

$ git add –A
$ git commit –m "Сообщение о фиксации"
$ git checkout master
Перешел на ветку master
$ git merge новая ветка
  

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

Подводя итог, вот команды для создания новой ветки, выполнения некоторых коммитов и объединения ее обратно в мастер:

  $ мастер проверки git
$ git branch новая ветка
$ git checkout новая ветка

# . .. разработать код ...

$ git add –A
$ git commit –m "Сообщение о фиксации"
$ git checkout master
$ git merge новая ветка
  
Об авторе

Эта статья была написана Якобом Стопаком, консультантом по программному обеспечению и разработчиком, страстно желающим помочь другим улучшить свою жизнь с помощью кода.Джейкоб является создателем Initial Commit — сайта, призванного помочь любознательным разработчикам узнать, как написаны их любимые программы. Его избранный проект помогает людям изучать Git на уровне кода.

Git застрял на мастере | ОБЪЕДИНЕНИЕ

Как упоминалось в комментарии @ Holger, вы можете выполнить git merge --abort , чтобы прервать слияние. Однако, возможно, вы не захотите этого делать. Слияние происходит потому, что удаленный ( origin ) имеет изменения, которых у вас нет локально. Ваша история может выглядеть примерно так:

  * - * - A - B - C [мастер, гармит / мастер]
       \
        D - E [происхождение / хозяин]
  

(Обратите внимание, что master == harmeet / master . Я подойду к этому через минуту.)

Есть три решения: слияние, перебазирование или принудительное обновление.

Объединить

Самым простым решением было бы просто завершить слияние. Для этого разрешите любые конфликты в вашем редакторе, добавьте git add. и коммит с git commit . Тогда ваша история будет выглядеть так:

  * - * - A - B --- C [гармит / мастер]
       \ \
        \ F [мастер]
         \ /
          D - E [происхождение / хозяин]
  

, а затем вы можете git push origin master для обновления origin и git push harmeet master для обновления harmeet .

Rebase

Если вы хотите сохранить линейную историю, прервите слияние, а затем выполните:

  git pull --rebase
  

(Если есть какие-либо конфликты, разрешите их и продолжите с git rebase - продолжить .)

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

  * - * - A - B - C [гармит / мастер]
       \
        D - E [происхождение / хозяин]
            \
             B '- C' [мастер]
  

Затем вы можете обновить origin с помощью:

  мастер git push origin
  

и принудительное обновление harmeet с:

  git push --force-with-lease мастер harmeet
  

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

  * - * - A - D - E - B '- C' [хозяин, происхождение / хозяин, harmeet / хозяин]
  

Force-обновление

Если вы действительно не хотите изменений из происхождения , вы можете сделать:

  git push --force-with-lease origin master
  

, и ваша история будет выглядеть так:

  * - * - A - B - C [хозяин, гармит / хозяин, происхождение / хозяин]
  

Если Git сообщает вам, что harmeet / master обновлен, то он находится в той же фиксации, что и ваш локальный master , если только кто-то не нажал на harmeet / master с момента вашей последней выборки.

Если ваша цель — получить изменения от origin (фиксирует D и E ) до harmeet , то вам нужно либо перебазировать, либо объединить, а затем нажать, как описано выше.

Каков наилучший (и самый безопасный) способ слить ветку Git с главной?

Это очень практичный вопрос, но все приведенные выше ответы непрактичны.

Нравится

  мастер проверки git
git pull origin master
git merge test
git push origin master
  

Этот подход имеет две проблемы :

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

  2. Он «сжал» все тестовые коммиты в один слитный коммит на главном сервере; то есть в основной ветке мы не можем видеть все журналы изменений тестовой ветки.

Итак, когда мы подозреваем, что будут конфликты, мы можем выполнить следующие операции git:

  git checkout test
мерзавец тянуть
мастер проверки git
мерзавец тянуть
git merge --no-ff --no-commit test
  

Тест слияние до фиксации , избегайте быстрой фиксации вперед на --no-ff ,

Если возник конфликт, мы можем запустить git status , чтобы проверить подробности конфликтов и попытаться разрешить

  git статус
  

Как только мы разрешаем конфликты или если конфликта нет, мы фиксируем и нажимаем на них

  git commit -m 'тестовая ветка слияния'
git push
  

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

Итак, лучший метод — использовать rebase вместо merge (предположим, когда за это время мы разрешили конфликты веток).

Ниже приведен один простой пример, для расширенных операций см. Http://git-scm.com/book/en/v2/Git-Branching-Rebasing

.

  мастер проверки git
мерзавец тянуть
git checkout test
мерзавец тянуть
git rebase -i мастер
мастер проверки git
git merge test
  

Да, когда вы закончите, все коммиты тестовой ветки будут перемещены в начало главной ветки.Основное преимущество перебазирования заключается в том, что вы получаете линейную и гораздо более чистую историю проекта.

Единственное, чего вам нужно избегать: никогда не используйте rebase в общедоступной ветке, например, в главной ветке.

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

  мастер проверки git
git rebase -i test
  

Подробная информация для https://www. atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing

приложение:

Мастер слияния Git в функциональную ветку

У вас должна быть возможность переустановить свою ветку на master:

  git checkout feature1
git rebase master
  

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

  git rebase --skip
  

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

Для более подробного обсуждения обратитесь к документации по Git на git rebase (https: // git-scm.com / docs / git-rebase), которые охватывают именно этот вариант использования.

================ Изменить для дополнительного контекста ====================

Этот ответ был предоставлен специально на вопрос, заданный @theomega, с учетом его конкретной ситуации. Обратите внимание на эту часть:

Я хочу предотвратить […] коммиты в моей ветке функции, которые не имеют отношения к реализации этой функции.

Перебазирование его частной ветки на master — это именно то, что даст такой результат.Напротив, слияние мастера в его ветку будет делать именно то, что он конкретно не хочет, : добавление фиксации, которая не связана с реализацией функции, над которой он работает, через свою ветку.

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

  • только частные ветки (т.е. которые существуют только в вашем локальном репозитории и не были переданы другим). Повторное размещение общих веток «сломает» копии, которые могут быть у других людей.
  • , если вы хотите интегрировать изменения из ветки (будь то главная или другая ветка) в ветку, которая является общедоступной (например, вы подтолкнули ветку, чтобы открыть запрос на перенос, но теперь есть конфликты с главной веткой, и вам нужно обновите свою ветку, чтобы разрешить эти конфликты), вам нужно будет объединить их (например, с git merge master , как в ответе @Sven).
  • , вы также можете объединять ветки в свои локальные частные ветки, если это ваше предпочтение, но имейте в виду, что это приведет к «чужим» коммитам в вашей ветке.

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

Как безопасно объединить ветку с мастером в Git

Ниже приводится сообщение в гостевом блоге, написанное Карлосом Шульцем.

Возможности Git для ветвления и слияния мощные, но они могут сбивать с толку новичков. Сегодня мы вносим свой вклад в ваше понимание Git, отвечая на вопрос заголовка: как объединить ветку в master ?

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

Давайте углубимся.

Git Merge Branch to Master Основы: Начиная с начала

Без лишних слов, давайте начнем с основ ветвления и слияния Git.

Как работают ветви в Git?

Репозиторий Git содержит объектов и ссылок . Основными объектами в репозитории Git являются коммиты , , которые представляют собой моментальные снимки точки в истории проекта.Коммиты указывают на своих предшественников (называемых родителями), и из отношений между коммитами мы получаем историю изменений. Объекты в репозитории Git неизменяемы. Например, вы не можете ничего изменить в коммите или изменить его положение в истории, несмотря на то, что для этого есть команды. С другой стороны, ссылки — это метки, которые вы прикрепляете к фиксации, и, в отличие от объектов, ссылки можно перемещать.

Основным типом ссылки в Git является ветка .Когда вы создаете ветку из точки в истории, Git создает новую ссылку, указывающую на этот коммит. Еще одна важная ссылка в Git называется HEAD. HEAD указывает текущую точку в истории и используется такими командами, как git log , чтобы определить, с чего начать задачу.

На рисунке ниже мы видим репозиторий с тремя коммитами. HEAD указывает на главную ветку , которая на данный момент является единственной доступной веткой.

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

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

Что такое Git Merge?

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

Для этого предназначена команда git merge . Это позволяет вам интегрировать все изменения (т. Е. Коммиты), сделанные в другой ветке, в вашу текущую ветку с точки, в которой ветки разошлись.

Как объединить филиалы?

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

Чтобы использовать команду слияния в ее наиболее распространенной форме, вы должны передать исходную ветвь — в нашем случае example — команде в качестве параметра. Это означает, что вы должны быть в ветке, которая получит изменения. Итак, в сценарии на рисунке, допустим, вы не находитесь в ветви master , и вы хотите объединить пример с master . Вам нужно будет сделать только это:

git checkout master # переход на главную ветку
git merge example

В нашем сценарии пример указывает на ту же фиксацию, что и master , что означает, что никаких изменений для интеграции, и Git просто отвечает: «Уже обновлено.”

Типы слияний

Но что, если бы были изменения для интеграции? Как Git объединит их? Давайте рассмотрим это, узнав о различных типах слияния, которые предоставляет Git.

Fast-Forward Merge

Самый простой тип слияния в Git называется fast-forward . Git выполняет этот тип слияния, когда только исходная ветка содержит новые изменения с момента расхождения. Продолжим предыдущий сценарий. Предположим, что после создания ветки example мы добавляем в эту ветку пару коммитов. Репозиторий теперь выглядит так:

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

git switch master
git merge example

Git завершит слияние и отобразить сообщение о том, что была выполнена «быстрая перемотка вперед». Это означает, что до слияния ветка master находилась за веткой example . У него не было собственных расходящихся коммитов.Итак, слияние здесь просто связано с тем, чтобы master догнал исходную ветку. Вот визуальное представление репозитория после слияния:

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

Трехстороннее слияние

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

git reset --hard HEAD ~ 2
touch README.md
git add.
git commit -m "Добавить файл readme"

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

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

Что случилось? Поскольку две ветви содержали эксклюзивные изменения, перемотка вперед была невозможна, поэтому Git выполнил трехстороннее слияние . Он называется «трехстороннее слияние», потому что для определения результата слияния (например, какие версии одного и того же файла выбрать, если в каждой ветке есть различия), Git должен искать в трех местах: в текущей ветке, которую вы используете. есть, ветка, из которой вы пытаетесь слиться, и точка, в которой они разошлись.

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

Как мне объединить ветку в мастер? Несколько дополнительных советов

Вы уже видели, что слияние с веткой master — это просто запуск git checkout master , за которым следует git merge .По крайней мере, это основы. Как и когда это сделать, будет зависеть от стратегии ветвления , которую примет ваша команда.

Прежде чем мы подведем итоги, вот несколько дополнительных советов по слиянию, которые могут пригодиться.

1. Сжатие коммитов

Представьте, что вы хотите интегрировать изменения из одной ветки с другой ветвью, но вы не можете или не хотите объединять исходные коммиты как есть. Вместо этого вы хотите объединить все изменения в одну фиксацию с выбранным вами сообщением.Для этого вам просто нужно использовать опцию –squash при слиянии:

git checkout branch
git merge --squash

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

После фиксации вы можете удалить исходную ветвь.Когда вы попытаетесь сделать это с помощью git branch -d , Git покажет вам следующее сообщение:

error: Branch «» не полностью объединен.
Если вы уверены, что хотите удалить его, запустите 'git branch -D '.

Git считает, что у вас нет изменений из другой ветки, но они есть. У вас просто есть коммит с хешем, который отличается от хэша коммитов в исходной ветке, и это информация, которую Git использует, чтобы определить, полностью ли объединена ветка.Поскольку вы знаете лучше, вы можете удалить ветку, заменив «-d» на «-D» (с заглавной буквой D), как советует сам Git.

2. Использование опции «Без фиксации»

Использование опции –squash дает вам больше контроля при слиянии. Однако это приводит к регулярной фиксации. Git даже думает, что вы не включили изменения из другой ветки. Если вы хотите остановиться прямо перед фиксацией, чтобы настроить некоторые вещи, но все же хотите, чтобы в результате этого происходила фиксация слияния, вы должны использовать параметр no-commit , как в git merge –no-commit < имя-ветки>.

Если все работает нормально, Git сообщает:

Автоматическое слияние прошло успешно; остановлен перед фиксацией по запросу.

Теперь вы можете включить или отключить изменения, а затем зафиксировать их, когда будете готовы. Разница в том, что, в отличие от –no-squash , использование –no-commit приводит к фиксации слияния.

3. Переопределение локальных изменений при слиянии

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

Ошибка : ваши локальные изменения в следующие файлы будут перезаписаны слиянием:

Пожалуйста, зафиксируйте свои изменения или сохраните их перед слиянием.
Прерывание.

Это защитный механизм, предоставляемый Git для предотвращения потери работы. Но что, если вы действительно хотите отменить локальные изменения? В этом случае перед объединением выполните команду git reset –hard . Осторожно: в этом случае ваши изменения исчезнут навсегда.

Ветвление — это инструмент: не злоупотребляйте им

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

Мы не рассмотрели вопрос о том, следует ли интенсивно использовать ветвление. Часто команды слишком взволнованы тем, насколько дешево ветвление в Git, и принимают стратегии ветвления, которые являются сложными, подверженными ошибкам и могут вызывать задержки при интеграции и .

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

Спасибо за прочтение и до следующего раза!

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

Как разрешить конфликт слияния git

Git — это стандартный менеджер репозитория исходного кода для проектов с открытым исходным кодом и многих проектов с закрытым исходным кодом. Эта статья показывает новым пользователям Git, как сделать что-то немного сложное, но фундаментальное для его цели: разрешить конфликт git-merge.

Что такое git merge?

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

Если вы хотите перенести изменения из ветки в текущую ветку, вы используете команду git merge.Слияние берет все изменения в другой ветке и применяет их к текущей ветке.

Что такое конфликт слияния?

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

Если это произойдет, разработчик увидит следующую ошибку во время слияния git:

 

Автоматическое объединение [имя_файла1]
КОНФЛИКТ (содержимое): конфликт при объединении в [имя_файла1]
Автоматическое объединение не выполнено; исправить конфликты, а затем зафиксировать результат.

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

Как разрешить конфликт слияния git?

Git дает подсказку для разрешения конфликтов в своем сообщении об ошибке. Он говорит Конфликт слияния в [имя_файла1] , поэтому вы знаете, что с этим файлом возникла проблема.Затем он говорит, что устраняет конфликты, а затем фиксирует результат , поэтому, если вы будете следовать инструкциям, отредактировать файл, а затем зафиксировать его, все должно работать нормально. Давайте посмотрим на это в действии.

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

Начните с пустого каталога и запустите git init:

 

$ ls -l
$ git init
Инициализированный пустой репозиторий Git в /home/bob/example/.git/
$

Теперь создайте файл README и зафиксируйте изменения:

 

$ echo "Это новый файл README"> README.md
$ cat README.md
Это новый файл README
$ git add README.md
$ git commit -m "Файл README добавлен"
1 файл изменен, 1 вставка (+)
режим создания 100644 README. md
$ git status
На мастере ветки
ничего не фиксировать, рабочее дерево очищено
$

Создать новую ветку:

 

$ git checkout -b "branch_to_create_merge_conflict"
Переключился на новую ветку 'branch_to_create_merge_conflict'

В новом отделении:

 

$ git branch
* branch_to_create_merge_conflict
master

Внести правку:

 Это новый файл README 

Это правка в ветке

Теперь зафиксируйте это изменение:

 

$ vim README.md
$ git add README.md
$ git commit -m "Изменения, внесенные в README в ветке"
[branch_to_create_merge_conflict 9c5e88a] Изменения, внесенные в README в ветке
1 файл изменен, 2 вставки (+)

Вернитесь в основную ветку, отредактируйте README в строке 3 чем-нибудь другим и зафиксируйте это.

Переход на главную ветку:

 

$ git checkout master
переключился на ветку master

Отредактируйте README:

 Это новый файл README 

Это редактирование в главной ветке

Подтвердите редактирование:

 

$ git add README. md
$ git commit -m "Изменения, внесенные в README в главной ветке"
[master 7ea2985] Изменения, внесенные в README в главной ветке
1 файл изменен, 2 вставки (+)

Объедините ветку с мастером, чтобы увидеть ошибку:

 

$ git branch
branch_to_create_merge_conflict
* master
$ git merge branch_to_create_merge_conflict
Автоматическое слияние README.md
CONFLICT (контент): конфликт слияния в README.md
Ошибка автоматического слияния; исправить конфликты, а затем зафиксировать результат.

Теперь войдите в файл README, как просит Git, чтобы посмотреть, как он выглядит:

 Это новый файл README 

<<<<<<< HEAD
Это редактирование в главной ветке
=======
Это редактирование в ветке
>>>>>>> branch_to_create_merge_conflict

Как видите, Git добавил некоторый синтаксис, включающий семь символов «меньше», <<<<<<< и семь символов «больше», >>>>>>> , разделенных семью знаками равенства. , ======= .Их можно найти с помощью редактора, чтобы быстро найти, где нужно внести правки.

В этом блоке есть два раздела:

  • Символы «меньше» обозначают изменения в текущей ветке (в данном случае «HEAD», что является другим словом для вашей текущей ветки), а знаки равенства обозначают конец первого раздела.
  • Второй раздел — это правки, сделанные при попытке слияния; он начинается со знаков равенства и заканчивается знаками «больше».

Как разработчик, вы решаете, что остается, а что уходит. Внесите необходимые изменения и закройте файл:

.

 Это новый файл README 

Это правка в ветке

Как видите, это сохраняет правки ветки. Вы можете запустить git status, чтобы увидеть дальнейшие инструкции:

 $ vim README.md 
$ git status
На мастере филиала
У вас есть несвязанные пути.
(устраните конфликты и запустите "git commit")
(используйте «git merge --abort», чтобы прервать слияние)

Несвязанные пути:
(используйте «git add. .. "для обозначения разрешения)
оба изменены: README.md
в фиксацию изменений не добавлено (используйте" git add "и / или" git commit -a ")

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

Следуйте инструкциям, чтобы добавить файл и затем зафиксировать:

 $ git add README.md 
$ git status
На мастере филиала
Все конфликты устранены, но вы все еще объединяетесь.
(используйте «git commit» для завершения слияния)

Изменения, которые необходимо зафиксировать:
изменено: README.md

$ git commit
[master 9937ca4] Слияние ветки 'branch_to_create_merge_conflict'

Основные выводы и дополнительная литература

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

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

Веб-сайт и документация

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

Полное руководство по Git Merge и Git Rebase

Добро пожаловать в наше полное руководство по командам git merge и git rebase .Это руководство научит вас всему, что вам нужно знать об объединении нескольких веток с Git.

Git Merge

Команда git merge объединит любые изменения, внесенные в базу кода в отдельной ветке, в вашу текущую ветвь как новую фиксацию.

Синтаксис команды следующий:

  git merge ИМЯ ВЕТКИ  

Например, если вы в настоящее время работаете в ветке с именем dev и хотите объединить любые новые изменения, внесенные в ветку с именем new-features , вы должны ввести следующую команду:

  git merge new-features  

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

Создать новую ветку и зафиксировать изменения

  git checkout -b new-branch-name
git add.
git commit -m "<ваше сообщение о коммите>"  

Убрать их

  git stash # добавить их в тайник
git merge new-features # сделайте свое слияние
git stash pop # вернуть изменения в ваше рабочее дерево  

Отказаться от всех изменений

  git reset --hard # удаляет все ожидающие изменения  

Git Rebase

Перебазирование ветки в Git — это способ перемещения всю ветку до другой точки дерева. Самый простой пример — перемещение ветви вверх по дереву. Скажем, у нас есть ветка, которая расходится с основной веткой в ​​точке A:

  / o ----- o --- o - o ----- o --------- branch
--oo - A - o --- o --- o --- o ---- o - ooo --- master  

Когда вы перебазируете, вы можете переместить его следующим образом:

  / o ----- o --- o - o ----- o ------ филиал
--oo - A - o --- o --- o --- o ---- o - ooo master  

Для перебазирования убедитесь, что у вас есть все коммиты, которые вы хотите перебазировать в вашем главная ветка.Проверьте ветку, которую вы хотите перебазировать, и введите git rebase master (где master — ветка, которую вы хотите перебазировать).

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

  / --- o-o ветка
           / --- о-о-о-о --- о - о ------ особенность
---- o - ooA ---- o --- o - ooo - o - o- master  

После git rebase master branch или git rebase master , когда вы проверили ветка, вы получите:

  / --- oooo --- o - o ------ особенность
---- o - o-o-A ---- o --- o - o-o-o - o - o- мастер
                                  \ --- oo ветка  

Git rebase интерактивно в консоли

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

  • Введите git rebase - i HEAD ~ 5 , где последнее число — любое количество коммитов от самых последних назад, которые вы хотите просмотреть.
  • В vim нажмите esc , затем i , чтобы начать редактирование теста.
  • С левой стороны вы можете перезаписать pick с помощью одной из команд ниже. Если вы хотите превратить фиксацию в предыдущую и отбросить сообщение фиксации, введите f вместо pick фиксации.
  • Сохраните текстовый редактор и закройте его.
  • Когда перебазирование остановлено, внесите необходимые изменения, затем используйте git rebase --continue до тех пор, пока перебазирование не будет успешным.
  • Если перезагрузка прошла успешно, вам нужно принудительно отправить свои изменения с помощью git push -f , чтобы добавить обновленную версию в удаленный репозиторий.
  • Если есть конфликт слияния, есть несколько способов исправить это, в том числе следуя рекомендациям в этом руководстве. Один из способов — открыть файлы в текстовом редакторе и удалить ненужные части кода. Затем используйте git add <имя файла> , а затем git rebase --continue . Вы можете пропустить конфликтующую фиксацию, введя git rebase --skip , остановить перебазирование, запустив git rebase --abort в консоли.
  pick 452b159 <сообщение для этого коммита>
выберите 7fd4192 <сообщение для этого коммита>
выберите c1af3e5 <сообщение для этого коммита>
выберите 5f5e8d3 <сообщение для этого коммита>
выберите 5186a9f <сообщение для этого коммита>

# Rebase 0617e63..5186a9f на 0617e63 (30 команд)
#
# Команды:
# p, pick = использовать фиксацию
# r, reword = использовать фиксацию, но прекратить редактировать сообщение фиксации.
# e, edit = использовать фиксацию, но прекратить изменять или добавлять фиксацию.
# s, squash = использовать фиксацию, объединить с предыдущей фиксацией и остановить редактирование сообщения фиксации.# f, fixup = как "squash", но сбросить сообщение журнала этой фиксации, таким образом, не останавливается.
# x, exec = run команда (остальная часть строки) с использованием оболочки
# d, drop = удалить фиксацию
#
# Эти строки можно переупорядочить; они выполняются сверху вниз. 
#
# Если вы удалите здесь строчку, ЧТО COMMIT БУДЕТ УТЕРЯНЫ.
#
# Однако, если вы удалите все, перебазирование будет прервано.
#
# Обратите внимание, что пустые коммиты закомментированы  

Конфликты слияния

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

  КОНФЛИКТ (контент): конфликт слияния в resumé.txt Автоматическое слияние не выполнено; исправить конфликты, а затем зафиксировать результат.  

Если вы посмотрите файл resumé.txt в редакторе кода, вы увидите, где произошел конфликт:

  <<<<<<< HEAD
Адрес: 808 South Street.
=======
Адрес: 505 North Street.
>>>>>>> updated_address  

Git добавил несколько дополнительных строк в файл:

  • <<<<<<< HEAD
  • =======
  • >>> >>>> updated_address

Думайте о ======= как о разделительной линии конфликта. Все между <<<<<<< HEAD и ======= - это содержимое текущей ветки, на которую указывает ссылка HEAD. С другой стороны, все между ======= и >>>>>>> updated_address - это контент в объединяемой ветке, updated_address .

Git Merge vs Git Rebase

И git merge , и git rebase - очень полезные команды, и одна не лучше другой.Однако между двумя командами есть некоторые очень важные различия, которые следует учитывать вам и вашей команде.

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

git rebase - очень мощная функция. При этом рискованно и , если не использовать правильно.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *