<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rebase on kenji.blog</title><link>http://kenji.blog/ru/tags/rebase/</link><description>Recent content in Rebase on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ru/tags/rebase/index.xml" rel="self" type="application/rss+xml"/><item><title>【Команды Git】Разница между 'rebase' и 'merge', и их правильное использование на практике</title><link>http://kenji.blog/ru/p/git-rebase-vs-merge-practical-guide/</link><pubDate>Sun, 13 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/ru/p/git-rebase-vs-merge-practical-guide/</guid><description>&lt;img src="http://kenji.blog/p/git-rebase-vs-merge-practical-guide/img/eyecatch.jpg" alt="Featured image of post 【Команды Git】Разница между 'rebase' и 'merge', и их правильное использование на практике" />&lt;h1 id="1-введение-почему-выбор-между-merge-и-rebase--это-вечная-проблема">1. Введение: почему выбор между «merge» и «rebase» — это вечная проблема
&lt;/h1>&lt;p>Git является незаменимой системой контроля версий в современной разработке программного обеспечения. Когда несколько разработчиков одновременно вносят изменения в кодовую базу, мощная модель ветвления Git демонстрирует свою эффективность. Однако в командной разработке спор о том, что следует использовать: &lt;code>merge&lt;/code> или &lt;code>rebase&lt;/code>, является одной из тем, которая постоянно беспокоит разработчиков, от новичков до экспертов.&lt;/p>
&lt;p>В этой статье мы подробно рассмотрим различия в механизмах работы &lt;code>git merge&lt;/code> и &lt;code>git rebase&lt;/code>, начиная с внутренней структуры Git — DAG (направленного ациклического графа) и математических свойств хешей коммитов. Затем мы тщательно объясним, как правильно использовать их на практике, сопровождая это конкретными рабочими процессами. Понимая не только сами команды, но и то, какие вычисления Git выполняет «под капотом», вы избавитесь от страха перед конфликтами и сможете создавать чистую, легко отслеживаемую историю.&lt;/p>
&lt;hr>
&lt;h1 id="2-внутренняя-структура-git-хеши-коммитов-и-объектная-модель">2. Внутренняя структура Git: хеши коммитов и объектная модель
&lt;/h1>&lt;p>Чтобы понять, как Git интегрирует историю, сначала нужно узнать, как он хранит данные. Git не просто сохраняет различия (патчи) изменений файлов; он сохраняет снимки всей файловой системы на определенный момент времени.&lt;/p>
&lt;h2 id="21-криптографические-свойства-хешей-коммитов">2.1 Криптографические свойства хешей коммитов
&lt;/h2>&lt;p>Каждый коммит в Git однозначно идентифицируется 40-значным шестнадцатеричным числом, вычисленным на основе его содержимого с помощью хеш-функции SHA-1 (Secure Hash Algorithm 1). Объект коммита состоит из следующих элементов:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Указатель на объект Tree&lt;/strong>: снимок структуры каталогов и файлов (Blob) на тот момент времени.&lt;/li>
&lt;li>&lt;strong>Указатель на родительский коммит&lt;/strong>: хеш-значения одного или нескольких родительских коммитов (первый коммит не имеет родителя, а коммит слияния имеет два или более родителей).&lt;/li>
&lt;li>&lt;strong>Информация об авторе (Author)&lt;/strong>: кто написал код и когда.&lt;/li>
&lt;li>&lt;strong>Информация о коммитере (Committer)&lt;/strong>: кто создал и применил коммит, и когда.&lt;/li>
&lt;li>&lt;strong>Сообщение коммита&lt;/strong>: текст, объясняющий цель изменений.&lt;/li>
&lt;/ol>
&lt;p>В математическом выражении хеш-значение $H(C)$ для объекта коммита $C$ определяется следующим образом:&lt;/p>
$$
H(C) = \text{SHA-1}( \text{tree} \parallel \text{parent} \parallel \text{author} \parallel \text{committer} \parallel \text{message} )
$$&lt;p>Здесь $\parallel$ обозначает конкатенацию данных. Из-за свойств хеш-функции изменение даже одного символа в сообщении коммита или другой родительский коммит приведут к генерации совершенно иного хеш-значения. Это означает, что &lt;strong>коммиты неизменяемы (Immutable)&lt;/strong>. Когда говорят, что &lt;code>rebase&lt;/code> «переписывает историю» (о чем пойдет речь позже), на самом деле это означает создание новых коммитов с похожим содержимым, но с другими хеш-значениями.&lt;/p>
&lt;p>Размер хеш-пространства составляет $2^{160}$, и вероятность коллизии (когда разные коммиты имеют одинаковое хеш-значение) $P$ можно приблизительно вычислить, используя парадокс дней рождения (Birthday Paradox), следующим образом (где $n$ — количество коммитов):&lt;/p>
$$
P(\text{collision}) \approx 1 - \exp\left(-\frac{n^2}{2 \times 2^{160}}\right)
$$&lt;p>Эта вероятность крайне мала, и на практике коллизия хешей коммитов Git практически невозможна.&lt;/p>
&lt;hr>
&lt;h1 id="3-теория-графов-и-dag-математическая-модель-истории-git">3. Теория графов и DAG: математическая модель истории Git
&lt;/h1>&lt;p>История коммитов Git моделируется как «направленный ациклический граф» (Directed Acyclic Graph, DAG) в теории графов.&lt;/p>
&lt;h2 id="31-что-такое-dag-направленный-ациклический-граф">3.1 Что такое DAG (направленный ациклический граф)
&lt;/h2>&lt;p>В графе $G = (V, E)$, $V$ — это множество коммитов (вершин), а $E$ — множество направленных ребер, указывающих на отношения родитель-ребенок между коммитами. В Git ребра направлены от «дочернего коммита к родительскому коммиту». Это связано с тем, что новые коммиты хранят указатели на предыдущие коммиты.&lt;/p>
&lt;pre class="mermaid">
graph BT
A[&amp;#34;Коммит A (Начальный)&amp;#34;]
B[&amp;#34;Коммит B&amp;#34;]
C[&amp;#34;Коммит C (Main)&amp;#34;]
D[&amp;#34;Коммит D (Feature)&amp;#34;]
E[&amp;#34;Коммит E (Merge)&amp;#34;]
B --&amp;gt; A
C --&amp;gt; B
D --&amp;gt; B
E --&amp;gt; C
E --&amp;gt; D
&lt;/pre>
&lt;p>Главной особенностью DAG является «отсутствие циклов». Благодаря этому алгоритмы обхода истории коммитов никогда не попадают в бесконечный цикл и гарантированно достигают конца (начального коммита).&lt;/p>
&lt;h2 id="32-топологическая-сортировка-и-порядок-истории">3.2 Топологическая сортировка и порядок истории
&lt;/h2>&lt;p>При отображении истории, например, с помощью команды &lt;code>git log&lt;/code>, DAG упорядочивается в одномерный список с использованием алгоритма топологической сортировки (Topological Sort). Для любого направленного ребра $u \to v$ в DAG ($u$ является потомком $v$), элементы сортируются так, чтобы $u$ находился перед $v$ в списке.&lt;/p>
&lt;hr>
&lt;h1 id="4-механизмы-и-типы-git-merge">4. Механизмы и типы git merge
&lt;/h1>&lt;p>&lt;code>git merge&lt;/code> — это самая базовая команда для интеграции изменений из веток. Однако, в зависимости от текущего состояния, Git автоматически выбирает разные стратегии слияния.&lt;/p>
&lt;h2 id="41-слияние-fast-forward---ff">4.1 Слияние Fast-Forward (&amp;ndash;ff)
&lt;/h2>&lt;p>Если целевая ветка (например, &lt;code>main&lt;/code>) является прямым предком исходной ветки (например, &lt;code>feature&lt;/code>), Git выполняет слияние «Fast-Forward» (перемотка вперед). Это операция, при которой новые коммиты не создаются, а просто указатель ветки перемещается вперед.&lt;/p>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;A&amp;#34;
commit id: &amp;#34;B&amp;#34;
branch feature
checkout feature
commit id: &amp;#34;C&amp;#34;
commit id: &amp;#34;D&amp;#34;
checkout main
merge feature
&lt;/pre>
&lt;p>Слияние Fast-Forward сохраняет историю линейной, но имеет тот недостаток, что теряется контекст: «какие коммиты были сгруппированы как разработка одной функции (feature)».&lt;/p>
&lt;h2 id="42-слияние-non-fast-forward---no-ff">4.2 Слияние Non-Fast-Forward (&amp;ndash;no-ff)
&lt;/h2>&lt;p>Если явно указать &lt;code>git merge --no-ff&lt;/code>, Git обязательно создаст новый «коммит слияния», даже если возможен Fast-Forward. Коммит слияния — это специальный коммит, имеющий двух родителей.&lt;/p>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;A&amp;#34;
commit id: &amp;#34;B&amp;#34;
branch feature
checkout feature
commit id: &amp;#34;C&amp;#34;
commit id: &amp;#34;D&amp;#34;
checkout main
commit id: &amp;#34;Main Work 1&amp;#34;
merge feature type: NORMAL
&lt;/pre>
&lt;p>Преимущество этого метода в том, что существование и история функциональной ветки четко остаются в DAG. При возникновении проблем можно выполнить &lt;code>git revert -m 1 &amp;lt;хеш коммита слияния&amp;gt;&lt;/code>, чтобы безопасно отменить (revert) всю функцию целиком за один раз.&lt;/p>
&lt;h2 id="43-алгоритм-трехстороннего-слияния-3-way-merge">4.3 Алгоритм трехстороннего слияния (3-Way Merge)
&lt;/h2>&lt;p>Если целевая и исходная ветки имеют свои собственные коммиты, Git выполняет трехстороннее слияние. При этом Git исследует DAG и находит «наименьшего общего предка» (Lowest Common Ancestor, LCA) двух веток.&lt;/p>
&lt;p>Вычислительная сложность алгоритма поиска LCA, $T_{\text{LCA}}$, выполняется за линейное время относительно количества вершин $|V|$ и ребер $|E|$:&lt;/p>
$$
T_{\text{LCA}} = \mathcal{O}(|V| + |E|)
$$&lt;p>Git сравнивает три состояния: «состояние LCA», «состояние текущей ветки» и «состояние другой ветки», и, если изменения не конфликтуют, автоматически генерирует коммит слияния.&lt;/p>
&lt;hr>
&lt;h1 id="5-механизм-git-rebase-и-реконструкция-истории">5. Механизм git rebase и реконструкция истории
&lt;/h1>&lt;p>В то время как &lt;code>git merge&lt;/code> «интегрирует» историю, &lt;code>git rebase&lt;/code> «реконструирует» (перебазирует) её.&lt;/p>
&lt;h2 id="51-что-происходит-за-кулисами-rebase">5.1 Что происходит за кулисами Rebase
&lt;/h2>&lt;p>Внутренняя работа при ребейзе ветки &lt;code>feature&lt;/code> на ветку &lt;code>main&lt;/code> (&lt;code>git rebase main&lt;/code>) выглядит следующим образом:&lt;/p>
&lt;ol>
&lt;li>Найти общего предка (LCA) веток &lt;code>feature&lt;/code> и &lt;code>main&lt;/code>.&lt;/li>
&lt;li>Сохранить разницу коммитов от LCA до конца ветки &lt;code>feature&lt;/code> во временную область.&lt;/li>
&lt;li>Переместить указатель ветки &lt;code>feature&lt;/code> на конец ветки &lt;code>main&lt;/code>.&lt;/li>
&lt;li>Последовательно применить сохраненные изменения (Cherry-Pick) поверх новой базы (конца &lt;code>main&lt;/code>), создавая новые коммиты.&lt;/li>
&lt;/ol>
&lt;pre class="mermaid">
graph TD
A[&amp;#34;Коммит A&amp;#34;] --&amp;gt; B[&amp;#34;Коммит B&amp;#34;]
B --&amp;gt; C[&amp;#34;Коммит C (Main)&amp;#34;]
B --&amp;gt; D[&amp;#34;Коммит D (Старая ветка Feature)&amp;#34;]
D -.-&amp;gt; E[&amp;#34;Коммит D&amp;#39; (Новая ветка Feature)&amp;#34;]
C --&amp;gt; E
style D stroke-dasharray: 5 5, fill: #f9f9f9, color: #999
&lt;/pre>
&lt;p>Здесь важно отметить, что коммит $D'$, созданный в результате ребейза, имеет &lt;strong>совершенно другой хеш&lt;/strong>, потому что у него другой родительский коммит, в отличие от исходного коммита $D$ (см. определение хеш-функции $H(C)$ выше).&lt;/p>
&lt;h2 id="52-интерактивный-ребейз-interactive-rebase">5.2 Интерактивный ребейз (Interactive Rebase)
&lt;/h2>&lt;p>Использование &lt;code>git rebase -i&lt;/code> (или &lt;code>--interactive&lt;/code>) позволяет вам управлять историей коммитов по своему усмотрению. Это самый мощный инструмент для очистки локальной истории.&lt;/p>
&lt;ul>
&lt;li>&lt;code>pick&lt;/code> : использовать коммит как есть&lt;/li>
&lt;li>&lt;code>reword&lt;/code> : изменить только сообщение коммита&lt;/li>
&lt;li>&lt;code>edit&lt;/code> : приостановить ребейз для изменения содержимого коммита&lt;/li>
&lt;li>&lt;code>squash&lt;/code> : объединить этот коммит с предыдущим, а также объединить их сообщения&lt;/li>
&lt;li>&lt;code>fixup&lt;/code> : то же, что и &lt;code>squash&lt;/code>, но сообщение этого коммита отбрасывается&lt;/li>
&lt;li>&lt;code>drop&lt;/code> : полностью удалить коммит&lt;/li>
&lt;/ul>
&lt;p>С математической точки зрения, если в ветке есть $N$ коммитов, количество возможных вариаций линейной истории (перестановок) $P$, генерируемых путем изменения порядка при ребейзе, выглядит следующим образом:&lt;/p>
$$
P = N!
$$&lt;p>Git предоставляет разработчикам $N!$ степеней свободы, позволяя поддерживать историю в логичном и красивом состоянии.&lt;/p>
&lt;hr>
&lt;h1 id="6-золотое-правило-ребейза-the-golden-rule-of-rebase">6. Золотое правило ребейза (The Golden Rule of Rebase)
&lt;/h1>&lt;p>Команда &lt;code>rebase&lt;/code> очень мощная, но существует одно абсолютное правило.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>«Никогда не выполняйте ребейз публичной истории»&lt;/strong>
&lt;em>(Never rebase public history)&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h2 id="61-почему-нельзя-делать-ребейз-публичной-истории">6.1 Почему нельзя делать ребейз публичной истории?
&lt;/h2>&lt;p>Git — это распределенная система. Коммиты, которые вы запушили в &lt;code>origin/main&lt;/code>, клонируются (копируются) в локальные репозитории других разработчиков. Что произойдет, если вы сделаете ребейз уже запушенных коммитов, перепишете историю и принудительно перезапишете её с помощью &lt;code>git push --force&lt;/code>?&lt;/p>
&lt;p>Локальный DAG у других разработчиков и удаленный DAG кардинально разойдутся. Когда другой разработчик выполнит &lt;code>git pull&lt;/code>, Git попытается принудительно слить группы коммитов с разной историей, что приведет к огромному количеству конфликтов и дублирующихся коммитов (коммитов с одинаковыми изменениями, но разными хешами), повергая репозиторий в состояние паники.&lt;/p>
&lt;p>Железное правило гласит: ребейз следует применять &lt;strong>только к «локальным веткам, которыми вы еще ни с кем не поделились»&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="7-разрешение-конфликтов-и-git-rebase---continue">7. Разрешение конфликтов и git rebase &amp;ndash;continue
&lt;/h1>&lt;p>Конфликт возникает, когда несколько человек изменяют одно и то же место в одном и том же файле. Процесс разрешения конфликтов в &lt;code>merge&lt;/code> и &lt;code>rebase&lt;/code> отличается.&lt;/p>
&lt;h2 id="71-разрешение-конфликтов-в-merge">7.1 Разрешение конфликтов в Merge
&lt;/h2>&lt;p>В случае с &lt;code>git merge&lt;/code> разрешение конфликтов происходит &lt;strong>только один раз&lt;/strong>. Все конфликтующие участки исправляются за один раз, прямо перед созданием финального коммита слияния.&lt;/p>
&lt;h2 id="72-разрешение-конфликтов-в-rebase">7.2 Разрешение конфликтов в Rebase
&lt;/h2>&lt;p>В случае с &lt;code>git rebase&lt;/code>, из-за природы повторного применения коммитов один за другим, &lt;strong>существует вероятность возникновения конфликта на каждом коммите&lt;/strong>.&lt;/p>
&lt;p>Если во время ребейза возникает конфликт, Git приостанавливает процесс. Порядок разрешения следующий:&lt;/p>
&lt;ol>
&lt;li>Открыть редактор или IDE (например, VS Code) и вручную исправить маркеры конфликтов (&lt;code>&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code>, &lt;code>======&lt;/code>, &lt;code>&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code>).&lt;/li>
&lt;li>Добавить исправленный файл в индекс:
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git add &amp;lt;исправленный файл&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>Не создавая коммит, возобновить процесс ребейза:
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git rebase --continue
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>Если вы хотите прервать ребейз и вернуться к исходному состоянию, выполните следующую команду:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git rebase --abort
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>(※Если разрешение конфликта не требуется, и вы хотите полностью пропустить этот коммит, используйте &lt;code>git rebase --skip&lt;/code>)&lt;/p>
&lt;hr>
&lt;h1 id="8-правильное-использование-на-практике-практика-рабочих-процессов">8. Правильное использование на практике (практика рабочих процессов)
&lt;/h1>&lt;p>Итак, как же правильно выбирать между &lt;code>merge&lt;/code> и &lt;code>rebase&lt;/code> в реальной разработке? Здесь мы представим самый стандартный и безопасный подход.&lt;/p>
&lt;h2 id="81-сценарий-1очистка-локальной-истории-использование-rebase">8.1 【Сценарий 1】Очистка локальной истории (использование Rebase)
&lt;/h2>&lt;p>Предположим, что во время разработки в функциональной ветке накопилось много мелких коммитов (таких как «исправление опечатки», «временное сохранение» и т. д.). Перед созданием Pull Request (PR) вы используете интерактивный ребейз, чтобы организовать их в осмысленные блоки.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Выполнить, находясь в ветке feature&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git rebase -i HEAD~5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># (Откроется редактор, используйте squash и fixup для очистки истории)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Это позволяет создать красивую историю коммитов, где намерения будут понятны ревьюерам.&lt;/p>
&lt;h2 id="82-сценарий-2следование-за-новейшей-веткой-main-использование-rebase">8.2 【Сценарий 2】Следование за новейшей веткой main (использование Rebase)
&lt;/h2>&lt;p>Если разработка затягивается, и чужие изменения постоянно сливаются в &lt;code>main&lt;/code>, ваша ветка &lt;code>feature&lt;/code> устаревает. В этом случае вы делаете ребейз ветки &lt;code>feature&lt;/code> на самую свежую &lt;code>main&lt;/code>, чтобы не отставать.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Получить новейшую информацию о main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git fetch origin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Перебазировать ветку feature поверх свежей main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git rebase origin/main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>В результате история становится линейной, что помогает избежать конфликтов при последующих слияниях. Кроме того, это предотвращает создание лишних коммитов слияния (например, &amp;ldquo;Merge branch &amp;lsquo;main&amp;rsquo; into feature&amp;rdquo;).&lt;/p>
&lt;h2 id="83-сценарий-3интеграция-завершенной-функции-использование-merge">8.3 【Сценарий 3】Интеграция завершенной функции (использование Merge)
&lt;/h2>&lt;p>Разработка в ветке &lt;code>feature&lt;/code> завершена, и настал этап интеграции в ветке &lt;code>main&lt;/code>. Здесь используется &lt;strong>&lt;code>git merge --no-ff&lt;/code>&lt;/strong> (это эквивалентно выбору «Create a merge commit» в Pull Request на GitHub и т.д.).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git checkout main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git merge --no-ff feature -m &lt;span class="s2">&amp;#34;Merge feature: Реализация функции входа пользователя&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git push origin main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Благодаря этому в DAG ветки &lt;code>main&lt;/code> останется исторический узел (коммит слияния), показывающий: «здесь была слита одна функция». При просмотре истории в будущем это облегчит отслеживание кода по функциональным блокам.&lt;/p>
&lt;hr>
&lt;h1 id="9-заключение-итоги">9. Заключение (итоги)
&lt;/h1>&lt;p>В работе с Git крайние подходы, такие как «решать всё только через Merge» или «делать всё линейным только через Rebase», имеют свои плюсы и минусы.&lt;/p>
&lt;p>Лучшая практика в реальной работе — это гибридный подход: &lt;strong>«красиво организовывать локальную приватную историю с помощью rebase, а публичную историю интеграции сохранять с контекстом через merge &amp;ndash;no-ff»&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Локально (личное рабочее пространство)&lt;/strong>: используйте &lt;code>rebase&lt;/code> для устранения лишних коммитов и поддержания линейной истории, следуя за актуальной основной линией.&lt;/li>
&lt;li>&lt;strong>Глобально (общее рабочее пространство)&lt;/strong>: используйте &lt;code>merge --no-ff&lt;/code> для записи существования функциональной ветки в DAG в виде коммита слияния, что облегчает реверт и отслеживание.&lt;/li>
&lt;/ul>
&lt;p>Понимая математические и архитектурные основы, такие как структура DAG и механизмы хеш-функций, команды Git превращаются из простого заучивания в «проектирование истории с определенным намерением». Соблюдая золотое правило ребейза и выбирая оптимальные команды в зависимости от ситуации, давайте создавать чистую, легко читаемую и поддерживаемую историю коммитов для всей команды.&lt;/p></description></item></channel></rss>