Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Лекция



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

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Главные ветви


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

  • master
  • develop


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

Мы считаем ветку origin/master главной. То есть, исходный код в ней должен находиться в состоянии production-ready в любой произвольный момент времени.

Ветвь origin/develop мы считаем главной ветвью для разработки. Хранящийся в ней код в любой момент времени должен содержать самые последние изданные изменения, необходимые для следующего релиза. Эту ветку также можно назвать «интеграционной». Она служит источником для сборки автоматических ночных билдов.

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

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

Вспомогательные ветви


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

Мы используем следующие типы ветвей:

  • Ветви функциональностей (Feature branches)
  • Ветви релизов (Release branches)
  • Ветви исправлений (Hotfix branches)


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

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

Ветви функциональностей (feature branches)


Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния
Могут порождаться от: develop
Должны вливаться в: develop
Соглашение о наименовании: все, за исключением master, develop, release-* или hotfix-*

Ветви функциональностей (feature branches), также называемые иногда тематическими ветвями (topic branches), используются для разработки новых функций, которые должны появиться в текущем или будущем релизах. При начале работы над функциональностью (фичей) может быть еще неизвестно, в какой именно релиз она будет добавлена. Смысл существования ветви функциональности (feature branch) состоит в том, что она живет так долго, сколько продолжается разработка данной функциональности (фичи). Когда работа в ветви завершена, последняя вливается обратно в главную ветвь разработки (что означает, что функциональность будет добавлена в грядущий релиз) или же удаляется (в случае неудачного эксперимента).

Ветви функциональностей (feature branches) обычно существуют в репозиториях разработчиков, но не в главном репозитории (origin).

Создание ветви функциональности (feature branch)


При начале работы над новой функциональностью делается ответвление от ветви разработки (develop).

$ git checkout -b myfeature develop
Switched to a new branch "myfeature"

Добавление завершенной функциональности в develop


Завершенная функциональность (фича) вливается обратно в ветвь разработки (develop) и попадает в следующий релиз.

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Отчет об изменениях)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

Флаг --no-ff вынуждает Git всегда создавать новый объект коммита при слиянии, даже если слияние может быть осуществлено алгоритмом fast-forward. Это позволяет не терять информацию о том, что ветка существовала, и группирует вместе все внесенные изменения. Сравните:

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

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

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

К сожалению, я еще не нашел, как можно настроить Git так, чтобы --no-ff было поведением по-умолчанию при слияниях. Но этот способ должен быть реализован.

Ветви релизов (release branches)


Могут порождаться от: develop
Должны вливаться в: develop и master
Соглашение о наименовании: release-*

Ветви релизов (release branches) используются для подготовки к выпуску новых версий продукта. Они позволяют расставить финальные точки над i перед выпуском новой версии. Кроме того, в них можно добавлять минорные исправления, а также подготавливать метаданные для очередного релиза (номер версии, дата сборки и т.д.). Когда вся эта работа выносится в ветвь релизов, главная ветвь разработки (develop) очищается для добавления последующих фич (которые войдут в следующий большой релиз).

Новую ветку релиза (release branch) надо порождать в тот момент, когда состояние ветви разработки полностью или почти полностью соответствует требованиям, соответствующим новому релизу. По крайней мере, вся необходимая функциональность, предназначенная к этому релизу, уже влита в ветвь разработки (develop). Функциональность, предназначенная к следующим релизам, может быть и не влита. Даже лучше, если ветки для этих функциональностей подождут, пока текущая ветвь релиза не отпочкуется от ветви разработки (develop).

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

Создание ветви релиза (release branch)


Ветвь релиза создается из ветви разработки (develop). Пускай, например, текущий изданный релиз имеет версию 1.1.5, а на подходе новый большой релиз, полный изменений. Ветвь разработки (develop) готова к «следующему релизу», и мы решаем, что этот релиз будет иметь версию 1.2 (а не 1.1.6 или 2.0). В таком случае мы создаем новую ветвь и даем ей имя, соответствующее новой версии проекта:

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

Мы создали новую ветку, переключились в нее, а затем выставили номер версии (bump version number). В нашем примере bump-version.sh — это вымышленный скрипт, который изменяет некоторые файлы в рабочей копии, записывая в них новую версию. (Разумеется, эти изменения можно внести и вручную; я просто обращаю Ваше внимание на то, что некоторые файлы изменяются.) Затем мы делаем коммит с указанием новой версии проекта.

Эта новая ветвь может существовать еще некоторое время, до тех пор, пока новый релиз окончательно не будет готов к выпуску. Об этом говорит сайт https://intellect.icu . В течение этого времени к этой ветви (а не к develop) могут быть добавлены исправления найденных багов. Но добавление крупных новых изменений в эту ветвь строго запрещено. Они всегда должны вливаться в ветвь разработки (develop) и ждать следующего большого релиза.

Закрытие ветви релиза


Когда мы решаем, что ветвь релиза (release branch) окончательно готова для выпуска, нужно проделать несколько действий. В первую очередь ветвь релиза вливается в главную ветвь (напоминаю, каждый коммит в master — это по определению новый релиз). Далее, этот коммит в master должен быть помечен тегом, чтобы в дальнейшем можно было легко обратиться к любой существовавшей версии продукта. И наконец, изменения, сделанные в ветви релиза (release branch), должны быть добавлены обратно в разработку (ветвь develop), чтобы будущие релизы также содержали внесенные исправления багов.

Первые два шага в Git:

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Отчет об изменениях)
$ git tag -a 1.2

Теперь релиз издан и помечен тегом.

Замечание: при желании, Вы также можете использовать флаги -s или -u <ключ>, чтобы криптографически подписать тег.

Чтобы сохранить изменения и в последующих релизах, мы должны влить эти изменения обратно в разработку. Делаем это так:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Отчет об изменениях)

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

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

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

Ветви исправлений (hotfix branches)


Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния
Могут порождаться от: master
Должны вливаться в: develop и master
Соглашение о наименовании: hotfix-*

Ветви для исправлений (hotfix branches) весьма похожи на ветви релизов (release branches), так как они тоже используются для подготовки новых выпусков продукта, разве лишь незапланированных. Они порождаются необходимостью немедленно исправить нежелательное поведение производственной версии продукта. Когда в производственной версии находится баг, требующий немедленного исправления, из соответствующего данной версии тега главной ветви (master) порождается новая ветвь для работы над исправлением.

Смысл ее существования состоит в том, что работа команды над ветвью разработки (develop) может спокойно продолжаться, в то время как кто-то один готовит быстрое исправление производственной версии.

Создание ветви исправлений (hotfix branch)



Ветви исправлений (hotfix branches) создаются из главной (master) ветви. Пускай, например, текущий производственный релиз имеет версию 1.2, и в нем (внезапно!) обнаруживается серьезный баг. А изменения в ветви разработки (develop) еще недостаточно стабильны, чтобы их издавать в новый релиз. Но мы можем создать новую ветвь исправлений и начать работать над решением проблемы:

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

Не забывайте обновлять номер версии после создания ветви!

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

$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbed6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)

Закрытие ветви исправлений


Когда баг исправлен, изменения надо влить обратно в главную ветвь (master), а также в ветвь разработки (develop), чтобы гарантировать, что это исправление окажется и в следующем релизе. Это очень похоже на то, как закрывается ветвь релиза (release branch).

Прежде всего надо обновить главную ветвь (master) и пометить новую версию тегом.

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Отчет об изменениях)
$ git tag -a 1.2.1

Замечание: при желании, Вы также можете использовать флаги -s или -u <ключ>, чтобы криптографически подписать тэг.



Следующим шагом переносим исправление в ветвь разработки (develop).



$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Отчет об изменениях)

У этого правила есть одно исключение: если в данный момент существует ветвь релиза (release branch), то ветвь исправления (hotfix branch) должна вливаться в нее, а не в ветвь разработки (develop). В этом случае исправления войдут в ветвь разработки вместе со всей ветвью релиза, когда та будет закрыта. (Хотя, если работа в develop требует немедленного исправления бага и не может ждать, пока будет завершено издание текущего релиза, Вы все же можете влить исправления (bugfix) в ветвь разработки (develop), и это будет вполне безопасно).

И наконец, удаляем временную ветвь:

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbed6).

Особенности и стратегии слияния веток git-merge


Считается, что «киллер фичей» СКВ Git является легковесное ветвление. Я ощутил это преимущество в полной мере, ведь я перешел на Git с SVN, где ветвление было достаточно дорогим процессом: для создания ветки нужно было скопировать весь рабочий каталог. В Git все проще: создание ветки подразумевает лишь создание нового указателя на определенный коммит в папке .git/refs/heads, который является файлом с 40 байтами текста, хешем коммита.

Основными командами пользовательского уровня для ветвления в Git являются git-branch, git-checkout, git-rebase, git-log и, конечно же, git-merge. Для себя я считаю git-merge зоной наибольшей ответственности, точкой огромной магической энергии и больших возможностей. Но это достаточно сложная команда, и даже достаточно длительный опыт работы с Git порой бывает недостаточным для освоение всех ее тонкостей и умения применить ее наиболее эффективно в какой-либо нестандартной ситуации.

Попробуем же разобраться в тонкостях git-merge и приручить эту великую магию.

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

Анатомия команды git merge


Если верить мануалу, команда имеет следующий синтаксис:

git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
[-s <strategy>] [-X <strategy-option>]
[--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]
git merge <msg> HEAD <commit>...
git merge --abort



По большому счету, в Git есть два вида слияния: перемотка (fast-forward merge) и «истинное» слияние (true merge). Рассмотрим несколько примеров обоих случаев.

«Истинное» слияние (true merge)


Мы отклоняемся от ветки master, чтобы внести несколько багов улучшений. История коммитов у нас получилась следующая:

master: A - B - C - D
                 \
feature:          X - Y



Выполним на ветке master git merge feature:

master: A - B - C - D - (M)
                 \      /
feature:          X - Y



Это наиболее частый паттерн слияния. В данном случае в ветке master создается новый коммит (M), который будет ссылаться на двух родителей: коммит D и коммит Y; а указатель master установится на коммит (M). Таким образом Git будет понимать, какие изменения соответствуют коммиту (M) и какой коммит последний в ветке master. Обычно коммит слияния делается с сообщением вроде «Merge branch 'feature'», но можно определить и свое сообщение коммита с помощью ключа -m.

Посмотрим историю коммитов в тестовом репозитории, который я создал специально для этого случая:

$ git log --oneline
9384bd (M)
beb5a4 D
5ce5b1 Y
7f13e7 X
d920dc C
35c217 B
84af94 A



А теперь посмотрим информацию о коммите (M):

$ git cat-file -p 9384bd
tree 25c78f9086384bd86a2ab9d00c7e41a56f01d04
parent beb5a4ad88e80467404473b94c3e0758dd8e0be
parent 5ce5b1edef64bd0d4e1039061a77be4d7182678
author Adre <adrey.pro@gmail.com> 1980475972 +0400
committer Adre <adrey.pro@gmail.com> 1980475972 +0400

(M)



Мы видим двух родителей, объект-дерево, соответствующее данному состоянию файлов репозитория, а так же информацию о том, кто виновен в коммите.

Посмотрим, куда ссылается указатель master:

$ cat .git/refs/heads/master
9384bd77304c09b81dcc4485da165923b96ed5f



Действительно, он теперь передвинут на коммит (M).

Squash и no-commit


Но что делать, если за содержимое ветки feature вас могут побить? К примеру, улучшение было небольшим, и вполне могло уместиться в один логичный коммит, но так вышло, что посреди работы вам было нужно убегать на электричку, а продолжать уже дома? В таком случае есть два выхода: экспорт репозитория с последующим импортом на другой машине, либо (особенно когда до электрички 10 минут, а до вокзала около километра) — сделать push origin feature.

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

git merge feature --squash объединит изменения всех коммитов ветки feature, перенесет их в ветку master и добавит в индекс. При этом коммит слияния не будет создан, вам нужно будет сделать его вручную.

Такого же поведения без параметра squash можно добиться, передав при слиянии параметр --no-commit.

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

master: A - B - C - D - Sq
                 \ 
feature:          X - Y




Позже, в случае выполнения «классического» git merge feature можно исправить это. Тогда история примет следующий вид:

master: A - B - C - D - Sq - (M)
                 \           /
feature:          X    -    Y




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

Перемотка (fast-forward merge)


Рассмотрим другой случай истории коммитов:

master: A - B - C
                 \
feature:          X - Y



Все как и в прошлый раз, но теперь в ветке master нет коммитов после ответвления. В этом случае происходит слияние fast-forward (перемотка). В этом случае отсутствует коммит слияния, указатель (ветка) master просто устанавливается на коммит Y, туда же указывает и ветка feature:

master, feature: A - B - C - X - Y



Чтобы предотвратить перемотку, можно использовать параметр --no-ff.
В случае, если мы выполним git merge feature --no-ff -m '(M)', мы получим уже такую картину:

master: A - B - C   -  (M)
                 \     /
feature:          X - Y



Если же для нас единственным приемлемым поведением является fast-forward, мы можем указать опцию --ff-only. В этом случае, если к слиянию не применима перемотка, будет выведено сообщение о невозможности совершить слияние. Именно так было бы, если бы мы добавили опцию --ff-only в самом первом примере, где после ответвления feature в ветке master был сделано коммит C.

Можно добавить, что при выполнении git pull origin branch_name применяется как раз что-то вроде --ff-only. То есть, в случае, если при слиянии с веткой origin/branch_name не приемлема перемотка, операция отменяется и выводится сообщении о невозможности выполнения.

Стратегии слияния


У команды git-merge есть интересный параметр, --strategy, стратегия. Git поддерживает следующие стратегии слияния:

  • resolve
  • recursive
  • ours
  • octopus
  • subtree

Стратегия 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»:

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

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

Процесс разработки с использованием систем контроля версий. Особенности создания веток в git, стратегии слияния

Стратегия 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 git@github.com:shacon/rack.git
$ git fetch rack_remote
warning: no common commits
remote: Counting objects: 384, done.
remote: Compressing objects: 100% (165/165), done.
remote: Total 3184 (delta 152), reused 270 (delta 175)
Receiving objects: 100% (384/384), 67.42 KiB | 4 KiB/s, done.
Resolving deltas: 100% (152/152), done.
From git@github.com: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 у нас в рабочем каталоге.

Заключение


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

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



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

создано: 2018-10-20
обновлено: 2021-03-13
132266



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Разработка программного обеспечения и информационных систем

Термины: Разработка программного обеспечения и информационных систем