<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Merge on kenji.blog</title><link>http://kenji.blog/es/tags/merge/</link><description>Recent content in Merge on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>es</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/es/tags/merge/index.xml" rel="self" type="application/rss+xml"/><item><title>【Comandos Git】Diferencias entre rebase y merge, y su uso correcto en la práctica</title><link>http://kenji.blog/es/p/git-rebase-vs-merge-practical-guide/</link><pubDate>Sun, 13 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/es/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 【Comandos Git】Diferencias entre rebase y merge, y su uso correcto en la práctica" />&lt;h1 id="1-introducción-por-qué-merge-o-rebase-es-un-dilema-eterno">1. Introducción: ¿Por qué &amp;ldquo;merge o rebase&amp;rdquo; es un dilema eterno?
&lt;/h1>&lt;p>Git es un sistema de control de versiones indispensable en el desarrollo de software moderno. Cuando múltiples desarrolladores cambian simultáneamente una base de código, el poderoso modelo de ramas de Git demuestra su valía. Sin embargo, en el desarrollo en equipo, el debate sobre &amp;ldquo;si usar &lt;code>merge&lt;/code> o &lt;code>rebase&lt;/code>&amp;rdquo; es uno de los temas que siempre preocupa a los desarrolladores, desde principiantes hasta expertos.&lt;/p>
&lt;p>En este artículo, desentrañaremos las diferencias en los mecanismos de &lt;code>git merge&lt;/code> y &lt;code>git rebase&lt;/code>, partiendo de la estructura interna de Git, el DAG (Grafo Dirigido Acíclico), y las propiedades matemáticas de los hashes de los commits. Luego, explicaremos a fondo cómo usar y diferenciar ambos en la práctica, acompañándolo con flujos de trabajo concretos. Al ir más allá de la simple introducción de comandos y comprender qué cálculos realiza Git en segundo plano, perderás el miedo a los conflictos y podrás construir un historial limpio y rastreable.&lt;/p>
&lt;hr>
&lt;h1 id="2-estructura-interna-de-git-hashes-de-commits-y-modelo-de-objetos">2. Estructura interna de Git: Hashes de commits y modelo de objetos
&lt;/h1>&lt;p>Para comprender cómo Git integra el historial, primero debemos saber cómo Git almacena los datos. Git no solo almacena las diferencias (parches) de los cambios en los archivos, sino que guarda una instantánea de todo el sistema de archivos en un momento dado.&lt;/p>
&lt;h2 id="21-propiedades-criptográficas-de-los-hashes-de-los-commits">2.1 Propiedades criptográficas de los hashes de los commits
&lt;/h2>&lt;p>Cada commit en Git se identifica de forma única por un número hexadecimal de 40 dígitos generado por la función hash SHA-1 (Secure Hash Algorithm 1) calculada a partir de su contenido. Un objeto commit consta de los siguientes elementos:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Puntero al objeto Tree&lt;/strong>: Una instantánea de la estructura de directorios y archivos (Blob) en ese momento.&lt;/li>
&lt;li>&lt;strong>Puntero al commit padre&lt;/strong>: El valor hash de uno o más commits padres (el primer commit no tiene padre, y un commit de fusión (merge) tiene dos o más padres).&lt;/li>
&lt;li>&lt;strong>Información del autor (Author)&lt;/strong>: Quién escribió el código y cuándo.&lt;/li>
&lt;li>&lt;strong>Información del confirmador (Committer)&lt;/strong>: Quién creó y aplicó el commit y cuándo.&lt;/li>
&lt;li>&lt;strong>Mensaje del commit&lt;/strong>: Texto que explica la intención del cambio.&lt;/li>
&lt;/ol>
&lt;p>Expresado matemáticamente, el valor hash $H(C)$ para un objeto commit $C$ se define de la siguiente manera:&lt;/p>
$$
H(C) = \text{SHA-1}( \text{tree} \parallel \text{parent} \parallel \text{author} \parallel \text{committer} \parallel \text{message} )
$$&lt;p>Aquí, $\parallel$ representa la concatenación de datos. Debido a las propiedades de la función hash, incluso cambiar un solo carácter en el mensaje del commit, o tener un commit padre diferente, generará un valor hash completamente distinto. Es decir, &lt;strong>los commits son inmutables (Immutable)&lt;/strong>. Cuando se dice más adelante que &lt;code>rebase&lt;/code> &amp;ldquo;reescribe el historial&amp;rdquo;, en realidad significa &amp;ldquo;crea nuevos commits con un contenido similar pero con valores hash diferentes&amp;rdquo;.&lt;/p>
&lt;p>El tamaño del espacio de hashes es $2^{160}$, y la probabilidad $P$ de que ocurra una colisión (que diferentes commits tengan el mismo valor hash) se puede aproximar utilizando la teoría de la paradoja del cumpleaños (Birthday Paradox) (donde $n$ es el número de commits):&lt;/p>
$$
P(\text{colisión}) \approx 1 - \exp\left(-\frac{n^2}{2 \times 2^{160}}\right)
$$&lt;p>Esta probabilidad es extremadamente baja, por lo que en la práctica es casi imposible que los hashes de los commits de Git colisionen.&lt;/p>
&lt;hr>
&lt;h1 id="3-teoría-de-grafos-y-dag-modelo-matemático-del-historial-de-git">3. Teoría de grafos y DAG: Modelo matemático del historial de Git
&lt;/h1>&lt;p>El historial de commits de Git se modela como un &amp;ldquo;Grafo Dirigido Acíclico (Directed Acyclic Graph, DAG)&amp;rdquo; en la teoría de grafos.&lt;/p>
&lt;h2 id="31-qué-es-un-dag-grafo-dirigido-acíclico">3.1 ¿Qué es un DAG (Grafo Dirigido Acíclico)?
&lt;/h2>&lt;p>En un grafo $G = (V, E)$, $V$ es el conjunto de commits (vértices), y $E$ es el conjunto de aristas dirigidas que indican la relación padre-hijo entre los commits. En Git, la dirección de la arista va &amp;ldquo;del commit hijo al commit padre&amp;rdquo;. Esto se debe a que un nuevo commit mantiene un puntero a los commits pasados.&lt;/p>
&lt;pre class="mermaid">
graph BT
A[&amp;#34;Commit A (Inicial)&amp;#34;]
B[&amp;#34;Commit B&amp;#34;]
C[&amp;#34;Commit C (Principal)&amp;#34;]
D[&amp;#34;Commit D (Característica)&amp;#34;]
E[&amp;#34;Commit E (Fusión)&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>La característica principal de un DAG es que &amp;ldquo;no existen ciclos&amp;rdquo;. Gracias a esto, los algoritmos que retroceden en el historial de commits no caen en bucles infinitos y pueden llegar con seguridad al final (el commit inicial).&lt;/p>
&lt;h2 id="32-ordenación-topológica-y-orden-del-historial">3.2 Ordenación topológica y orden del historial
&lt;/h2>&lt;p>Cuando se muestra el historial con comandos como &lt;code>git log&lt;/code> de Git, el DAG se ordena como una lista unidimensional mediante el algoritmo de ordenación topológica (Topological Sort). Para cualquier arista dirigida $u \to v$ en el DAG ($u$ es hijo de $v$), se reordenan para que $u$ aparezca antes que $v$ en la lista.&lt;/p>
&lt;hr>
&lt;h1 id="4-mecanismos-y-tipos-de-git-merge">4. Mecanismos y tipos de git merge
&lt;/h1>&lt;p>El comando más básico para integrar cambios de ramas es &lt;code>git merge&lt;/code>. Sin embargo, Git selecciona automáticamente diferentes estrategias de fusión según el estado actual.&lt;/p>
&lt;h2 id="41-fusión-fast-forward---ff">4.1 Fusión Fast-Forward (&amp;ndash;ff)
&lt;/h2>&lt;p>Si la rama de destino de la integración (ej: &lt;code>main&lt;/code>) es un ancestro directo de la rama de origen (ej: &lt;code>feature&lt;/code>), Git ejecuta una fusión &amp;ldquo;Fast-Forward (avance rápido)&amp;rdquo;. Es una operación que no crea un nuevo commit, sino que simplemente avanza el puntero de la rama.&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>La fusión Fast-Forward mantiene el historial lineal, pero tiene la desventaja de que se pierde el contexto de &amp;ldquo;qué grupo de commits se agruparon como el desarrollo de una sola característica (feature)&amp;rdquo;.&lt;/p>
&lt;h2 id="42-fusión-non-fast-forward---no-ff">4.2 Fusión Non-Fast-Forward (&amp;ndash;no-ff)
&lt;/h2>&lt;p>Si se especifica explícitamente &lt;code>git merge --no-ff&lt;/code>, siempre se creará un nuevo &amp;ldquo;commit de fusión (merge commit)&amp;rdquo;, incluso en situaciones donde es posible hacer un Fast-Forward. Un commit de fusión es un commit especial que tiene dos padres.&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;Trabajo Principal 1&amp;#34;
merge feature type: NORMAL
&lt;/pre>
&lt;p>La ventaja de este método es que la existencia y la historia de la rama de la característica quedan claramente registradas en el DAG. Cuando ocurre un problema, al ejecutar &lt;code>git revert -m 1 &amp;lt;hash del commit de fusión&amp;gt;&lt;/code>, es posible deshacer (revertir) de forma segura toda la característica a la vez.&lt;/p>
&lt;h2 id="43-algoritmo-de-fusión-de-3-vías-3-way-merge">4.3 Algoritmo de fusión de 3 vías (3-Way Merge)
&lt;/h2>&lt;p>Cuando las ramas de destino y origen tienen sus propios commits únicos, Git ejecuta una fusión de 3 vías. En este momento, Git explora el DAG y encuentra el &amp;ldquo;ancestro común más bajo (Lowest Common Ancestor, LCA)&amp;rdquo; de las dos ramas.&lt;/p>
&lt;p>La complejidad temporal $T_{\text{LCA}}$ del algoritmo para encontrar el LCA se puede ejecutar en tiempo lineal con respecto al número de vértices $|V|$ y aristas $|E|$:&lt;/p>
$$
T_{\text{LCA}} = \mathcal{O}(|V| + |E|)
$$&lt;p>Git compara 3 estados: &amp;ldquo;el estado del LCA&amp;rdquo;, &amp;ldquo;el estado de la rama actual&amp;rdquo; y &amp;ldquo;el estado de la otra rama&amp;rdquo;, y si los cambios no entran en conflicto, genera automáticamente un commit de fusión.&lt;/p>
&lt;hr>
&lt;h1 id="5-mecanismo-de-git-rebase-y-reconstrucción-del-historial">5. Mecanismo de git rebase y reconstrucción del historial
&lt;/h1>&lt;p>Mientras que &lt;code>git merge&lt;/code> &amp;ldquo;integra&amp;rdquo; el historial, &lt;code>git rebase&lt;/code> &amp;ldquo;reconstruye (reemplaza)&amp;rdquo; el historial.&lt;/p>
&lt;h2 id="51-los-movimientos-detrás-de-rebase">5.1 Los movimientos detrás de Rebase
&lt;/h2>&lt;p>El comportamiento interno al hacer rebase de la rama &lt;code>feature&lt;/code> a la rama &lt;code>main&lt;/code> (&lt;code>git rebase main&lt;/code>) es el siguiente:&lt;/p>
&lt;ol>
&lt;li>Encontrar el ancestro común (LCA) entre la rama &lt;code>feature&lt;/code> y la rama &lt;code>main&lt;/code>.&lt;/li>
&lt;li>Guardar las diferencias de los commits desde el LCA hasta la punta de la rama &lt;code>feature&lt;/code> en un área temporal.&lt;/li>
&lt;li>Mover el puntero de la rama &lt;code>feature&lt;/code> a la punta de la rama &lt;code>main&lt;/code>.&lt;/li>
&lt;li>Aplicar (Cherry-Pick) secuencialmente las diferencias guardadas sobre la nueva base (la punta de &lt;code>main&lt;/code>), una por una, y generar nuevos commits.&lt;/li>
&lt;/ol>
&lt;pre class="mermaid">
graph TD
A[&amp;#34;Commit A&amp;#34;] --&amp;gt; B[&amp;#34;Commit B&amp;#34;]
B --&amp;gt; C[&amp;#34;Commit C (Principal)&amp;#34;]
B --&amp;gt; D[&amp;#34;Commit D (Característica Antigua)&amp;#34;]
D -.-&amp;gt; E[&amp;#34;Commit D&amp;#39; (Nueva Característica)&amp;#34;]
C --&amp;gt; E
style D stroke-dasharray: 5 5, fill: #f9f9f9, color: #999
&lt;/pre>
&lt;p>Lo importante aquí es que el commit $D'$ generado por el rebase &lt;strong>tiene un commit padre diferente al del commit original $D$, por lo que tiene un valor hash completamente distinto&lt;/strong> (consulta la definición de la función hash $H(C)$ mencionada anteriormente).&lt;/p>
&lt;h2 id="52-rebase-interactivo-interactive-rebase">5.2 Rebase Interactivo (Interactive Rebase)
&lt;/h2>&lt;p>El uso de &lt;code>git rebase -i&lt;/code> (o &lt;code>--interactive&lt;/code>) permite manipular el historial de commits a tu antojo. Esta es la herramienta más poderosa para organizar el historial local.&lt;/p>
&lt;ul>
&lt;li>&lt;code>pick&lt;/code> : Utiliza el commit tal cual&lt;/li>
&lt;li>&lt;code>reword&lt;/code> : Modifica solo el mensaje del commit&lt;/li>
&lt;li>&lt;code>edit&lt;/code> : Pausa para modificar el contenido del commit&lt;/li>
&lt;li>&lt;code>squash&lt;/code> : Fusiona este commit con el commit anterior y combina sus mensajes&lt;/li>
&lt;li>&lt;code>fixup&lt;/code> : Igual que &lt;code>squash&lt;/code>, pero descarta el mensaje de este commit&lt;/li>
&lt;li>&lt;code>drop&lt;/code> : Elimina el commit por completo&lt;/li>
&lt;/ul>
&lt;p>Desde un punto de vista matemático, si una rama tiene $N$ commits, el número de variaciones (permutaciones) del historial lineal que se pueden generar reordenando el rebase, $P$, es:&lt;/p>
$$
P = N!
$$&lt;p>Git otorga a los desarrolladores la libertad de $N!$ formas, lo que permite mantener el historial en un estado lógico y hermoso.&lt;/p>
&lt;hr>
&lt;h1 id="6-la-regla-de-oro-del-rebase-the-golden-rule-of-rebase">6. La regla de oro del Rebase (The Golden Rule of Rebase)
&lt;/h1>&lt;p>Aunque &lt;code>rebase&lt;/code> es extremadamente poderoso, existe una regla absoluta.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>&amp;ldquo;Nunca debes hacer rebase en historiales públicos que ya se han compartido&amp;rdquo;&lt;/strong>
&lt;em>(Never rebase public history)&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h2 id="61-por-qué-no-debes-hacer-rebase-en-el-historial-público">6.1 ¿Por qué no debes hacer rebase en el historial público?
&lt;/h2>&lt;p>Git es distribuido. Los commits que has empujado (push) a &lt;code>origin/main&lt;/code> también han sido clonados (duplicados) en los repositorios locales de otros desarrolladores. Si reescribes el historial haciendo rebase a commits que ya han sido empujados y los sobrescribes forzadamente con &lt;code>git push --force&lt;/code>, ¿qué pasará?&lt;/p>
&lt;p>El DAG local de otros desarrolladores y el DAG remoto se bifurcarán fundamentalmente. Cuando otros desarrolladores ejecuten &lt;code>git pull&lt;/code>, Git intentará fusionar por la fuerza grupos de commits con historias diferentes, lo que causará una gran cantidad de conflictos y commits duplicados (mismos cambios pero con diferentes hashes), sumiendo el repositorio en el caos.&lt;/p>
&lt;p>La regla de oro es hacer rebase &lt;strong>&amp;ldquo;solo en ramas locales que aún no se han compartido con nadie&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="7-resolución-de-conflictos-y-git-rebase---continue">7. Resolución de conflictos y git rebase &amp;ndash;continue
&lt;/h1>&lt;p>Si varias personas modifican la misma parte del mismo archivo, se producirá un conflicto. El proceso de resolución de conflictos es diferente entre &lt;code>merge&lt;/code> y &lt;code>rebase&lt;/code>.&lt;/p>
&lt;h2 id="71-resolución-de-conflictos-en-merge">7.1 Resolución de conflictos en Merge
&lt;/h2>&lt;p>En el caso de &lt;code>git merge&lt;/code>, la resolución del conflicto ocurre &lt;strong>solo una vez&lt;/strong>. Justo antes de crear el commit de fusión final, se corrigen todos los conflictos a la vez.&lt;/p>
&lt;h2 id="72-resolución-de-conflictos-en-rebase">7.2 Resolución de conflictos en Rebase
&lt;/h2>&lt;p>En el caso de &lt;code>git rebase&lt;/code>, debido a su naturaleza de reaplicar los commits uno por uno, &lt;strong>pueden ocurrir conflictos en cada commit&lt;/strong>.&lt;/p>
&lt;p>Cuando ocurre un conflicto durante el rebase, Git pausa el proceso. El flujo de resolución es el siguiente:&lt;/p>
&lt;ol>
&lt;li>Abre tu editor o IDE (como VS Code) y corrige manualmente los marcadores de conflicto (&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>Agrega los archivos modificados al índice (index):
&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;archivo modificado&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>Sin crear un commit, reanuda el proceso de rebase:
&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>Si deseas cancelar el rebase por completo y volver al estado original, ejecuta el siguiente comando:&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>(※ Si no necesitas resolver un conflicto y quieres omitir ese commit en particular, usa &lt;code>git rebase --skip&lt;/code>)&lt;/p>
&lt;hr>
&lt;h1 id="8-uso-correcto-en-la-práctica-práctica-de-flujo-de-trabajo">8. Uso correcto en la práctica (Práctica de flujo de trabajo)
&lt;/h1>&lt;p>Entonces, en un entorno de desarrollo real, ¿cómo deberíamos diferenciar el uso de &lt;code>merge&lt;/code> y &lt;code>rebase&lt;/code>? Aquí presentamos el enfoque más estándar y seguro.&lt;/p>
&lt;h2 id="81-escenario-1-organización-del-historial-de-trabajo-local-uso-de-rebase">8.1 【Escenario 1】 Organización del historial de trabajo local (Uso de Rebase)
&lt;/h2>&lt;p>Supongamos que durante el desarrollo en una rama de característica (feature), se han acumulado muchos commits pequeños (&amp;ldquo;corrección de error tipográfico&amp;rdquo;, &amp;ldquo;guardado temporal&amp;rdquo;, etc.). Antes de enviar un Pull Request (PR), usas un rebase interactivo para organizar estos en unidades significativas.&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"># Ejecutar estando en la rama 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"># (Se abre el editor, usas squash y fixup para limpiar el historial)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Esto permite crear un historial de commits hermoso y donde la intención sea clara para los revisores.&lt;/p>
&lt;h2 id="82-escenario-2-seguimiento-de-la-rama-main-más-reciente-uso-de-rebase">8.2 【Escenario 2】 Seguimiento de la rama main más reciente (Uso de Rebase)
&lt;/h2>&lt;p>Si el desarrollo se alarga y los cambios de otras personas se siguen fusionando en la rama &lt;code>main&lt;/code>, tu rama &lt;code>feature&lt;/code> quedará desactualizada. En este caso, haces un rebase de tu rama &lt;code>feature&lt;/code> sobre la última &lt;code>main&lt;/code> para seguirla.&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"># Obtener la última información de 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"># Mover la rama feature a la cima del main más reciente&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>Esto hace que el historial sea lineal y previene conflictos en fusiones posteriores. Además, evita que se generen commits de fusión innecesarios (&amp;ldquo;Merge branch &amp;lsquo;main&amp;rsquo; into feature&amp;rdquo;).&lt;/p>
&lt;h2 id="83-escenario-3-integración-de-una-característica-completada-uso-de-merge">8.3 【Escenario 3】 Integración de una característica completada (Uso de Merge)
&lt;/h2>&lt;p>El desarrollo en la rama &lt;code>feature&lt;/code> ha terminado y finalmente es la fase de integración en la rama &lt;code>main&lt;/code>. Aquí se usa &lt;strong>&lt;code>git merge --no-ff&lt;/code>&lt;/strong> (es equivalente a elegir &amp;ldquo;Create a merge commit&amp;rdquo; en un Pull Request en GitHub, etc.).&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: Implementación de la función de inicio de sesión de usuario&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>De esta manera, en el DAG de la rama &lt;code>main&lt;/code> queda un nodo en la historia (un commit de fusión) que indica &amp;ldquo;aquí se fusionó una característica completa&amp;rdquo;. Al mirar el historial más tarde, será más fácil seguir el código por unidad funcional.&lt;/p>
&lt;hr>
&lt;h1 id="9-conclusión-resumen">9. Conclusión (Resumen)
&lt;/h1>&lt;p>En las operaciones de Git, los enfoques extremos como &amp;ldquo;resolver todo con Merge&amp;rdquo; o &amp;ldquo;hacer todo lineal con Rebase&amp;rdquo; tienen sus propias ventajas y desventajas.&lt;/p>
&lt;p>La mejor práctica en el entorno laboral es un enfoque híbrido: &lt;strong>&amp;ldquo;Organizar bellamente el historial privado local con rebase, y preservar el contexto en el historial público de integración con merge &amp;ndash;no-ff&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Local (Espacio de trabajo personal)&lt;/strong>: Usar &lt;code>rebase&lt;/code> para eliminar commits inútiles, seguir la línea principal más reciente y mantener un historial lineal.&lt;/li>
&lt;li>&lt;strong>Global (Espacio de trabajo compartido)&lt;/strong>: Usar &lt;code>merge --no-ff&lt;/code> para registrar la existencia de ramas de características como commits de fusión en el DAG, facilitando la reversión y el rastreo.&lt;/li>
&lt;/ul>
&lt;p>Al comprender los fundamentos arquitectónicos y matemáticos, como la estructura del DAG y el mecanismo de las funciones hash, los comandos de Git se elevan de la simple memorización al &amp;ldquo;diseño intencional del historial&amp;rdquo;. Siguiendo la regla de oro del rebase, seleccionemos el comando óptimo según la situación y construyamos un historial de commits limpio que sea fácil de leer y mantener para todo el equipo.&lt;/p></description></item></channel></rss>