<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Claudio Sánchez</title>
    <description>The latest articles on DEV Community by Claudio Sánchez (@narkha).</description>
    <link>https://dev.to/narkha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F635941%2F3d7eaece-5fef-4afd-a72e-df833b239c80.jpg</url>
      <title>DEV Community: Claudio Sánchez</title>
      <link>https://dev.to/narkha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/narkha"/>
    <language>en</language>
    <item>
      <title>Git: how to salir de esta, repositorios remotos</title>
      <dc:creator>Claudio Sánchez</dc:creator>
      <pubDate>Sun, 26 Sep 2021 09:26:55 +0000</pubDate>
      <link>https://dev.to/narkha/git-how-to-salir-de-esta-repositorios-remotos-4352</link>
      <guid>https://dev.to/narkha/git-how-to-salir-de-esta-repositorios-remotos-4352</guid>
      <description>&lt;h2&gt;
  
  
  How to
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introducción&lt;/li&gt;
&lt;li&gt;Trastear con repositorios remotos&lt;/li&gt;
&lt;li&gt;Problemas al subir una rama&lt;/li&gt;
&lt;li&gt;Modificar algo en el repositorio remoto&lt;/li&gt;
&lt;li&gt;Git pull, ese comando problemático&lt;/li&gt;
&lt;li&gt;Renombrar una rama&lt;/li&gt;
&lt;li&gt;Mantener el  entorno limpio: cuando las ramas no dejan ver el bosque&lt;/li&gt;
&lt;li&gt;Modificar un tag&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;Un repositorio de código, dentro del contexto de los sistema de control de versiones, es un sistema para almacenar código y metadatos, como pueden ser el histórico de los archivos.&lt;/p&gt;

&lt;p&gt;Git es un sistema de control de versiones distribuido, en el que cada repositorio guarda una copia completa del código y los metadatos, pudiendo funcionar de manera independiente; en contraposición están los sistemas centralizados, en los que existe un único repositorio de código y los clientes se comunican con él para obtener o subir código, pero en ningún caso tienen una copia de los metadatos.&lt;/p&gt;

&lt;p&gt;Se denomina "&lt;a href="https://es.wikipedia.org/wiki/Control_de_versiones#Flujos_de_trabajo" rel="noopener noreferrer"&gt;flujo de trabajo&lt;/a&gt;" al cómo colaboran entre sí los repositorios de un sistema de control de versiones distribuido. El más común de ellos es el "&lt;em&gt;flujo de trabajo centralizado&lt;/em&gt;", en el que hay un repositorio central o de referencia, por ejemplo un repositorio en Bitbucket o GitHub; los desarrolladores se clonan ese repositorio en su local, obteniendo así un repositorio privado sobre el que pueden trabajar; hacen cambios en su repositorio local, como por ejemplo desarrollador una nueva feature, y envian esos cambios al repositorio central; y actualizan el repositorio privado con los cambios que otros desarrolladores han enviado al repositorio central. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45yc2sbnwowezbvidxyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45yc2sbnwowezbvidxyp.png" alt="flujo trabajo centralizado"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El tener un &lt;em&gt;"sistema de control de versiones distribuido"&lt;/em&gt; y acabar usando un &lt;em&gt;"flujo de trabajo centralizado"&lt;/em&gt; puede sonar contradictorio o exagerado ¿Por qué complicarse? ¿Por qué no usar simplemente un sistema de control de versiones centralizado como SVN? &lt;br&gt;
En un sistema de control de versiones centralizado cualquier operación, desde hacer un nuevo commit a consultar el log, implica comunicaciones con el servidor donde está alojado el repositorio, lo cual es mucho más lento que consultando una copia local como en Git; además de la lentitud, una perdida de conexión con el servidor central implica no poder ejecutar ningún comando; y la gestión de conflictos es más complicada, ya que habrá que resolverlos sobre cambios que todavía no se han podido commitear.&lt;br&gt;
Personalmente he trabajado con SVN y Git y me quedo sin ninguna duda con Git, pero como todo la elección dependerá de gustos y necesidades.&lt;/p&gt;

&lt;p&gt;Adicionalmente, un sistema de control de versiones distribuido permite evolucionar el flujo de trabajo dependiendo de como evolucione o crezca el proyecto; por poner un ejemplo, en el kernel de Linux usan el &lt;em&gt;"&lt;a href="https://git-scm.com/book/es/v2/Git-en-entornos-distribuidos-Flujos-de-trabajo-distribuidos#rwfdiag_c" rel="noopener noreferrer"&gt;flujo de trabajo dictador y tenientes&lt;/a&gt;"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Tras hacer &lt;code&gt;git clone &amp;lt;url repositorio&amp;gt;&lt;/code&gt; en el repositorio recién clonado habrá dos conjuntos de ramas: &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#introducci%C3%B3n"&gt;ramas locales&lt;/a&gt; y ramas remotas, &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;En un GUI&lt;/th&gt;
&lt;th&gt;En consola&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rah24p8u2ral10kvyoi.png" alt="ramas remota en IDE"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbgfm21tb4zcl8pymh9x.png" alt="ramas remotas en consola"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Las ramas remotas son referencias a ramas que existen en el repositorio remoto que se ha clonado, al que por defecto se le da el nombre de &lt;code&gt;origin&lt;/code&gt;, y que se actualizan con &lt;code&gt;git fetch&lt;/code&gt; si ha habido cambios en el repositorio remoto, o cuando este acepta los cambios que se le proponen al hacer &lt;code&gt;git push&lt;/code&gt;.&lt;br&gt;
Un ejemplo de rama remota sería &lt;code&gt;origin/master&lt;/code&gt;, y haría referencia a la rama &lt;code&gt;master&lt;/code&gt; en el repositorio remoto con nombre &lt;code&gt;origin&lt;/code&gt;.&lt;br&gt;
Una rama remota puede ser el "&lt;em&gt;upstream"&lt;/em&gt; de una rama local, pudiéndose entender "&lt;em&gt;lo que hay rio arriba&lt;/em&gt;" como que la rama local mira o sigue a la rama remota: cuando se hace &lt;code&gt;git pull&lt;/code&gt; se intenta actualizar la rama local con lo que haya en su &lt;em&gt;upstream&lt;/em&gt;; cuando se hace &lt;code&gt;git push&lt;/code&gt; se intenta actualizar el &lt;em&gt;upstream&lt;/em&gt; con los contenidos de la rama local. Y en ambos casos digo intentar porqué si la rama local ha divergido respecto del &lt;em&gt;upstream&lt;/em&gt;, sera necesarias algunas acciones que se irán viendo a lo largo del post.&lt;/p&gt;

&lt;p&gt;A la hora de visualizarlo, se puede hacer igual que con las ramas locales, solo que ahora habrá unas cuantas ramas más.&lt;br&gt;
Con un GUI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pndr8c2sg81gdoelidh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pndr8c2sg81gdoelidh.png" alt="Arbol ramas en IDE"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O por consola&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'%C(auto)%h %s%n%C(auto)%d%n'&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lfq57dlrhvmxyj572s2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lfq57dlrhvmxyj572s2.png" alt="Arbol ramas en consola"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Las ramas de los repositorios remotos añaden un nuevo nivel de complejidad a la gestión de las ramas: hay ramas como &lt;code&gt;pippin-merry&lt;/code&gt; que han adelantado a su &lt;em&gt;upstream&lt;/em&gt; &lt;code&gt;origin/pippin-merry&lt;/code&gt;; ramas como &lt;code&gt;aragorn-legolas-gimli&lt;/code&gt; que se han quedado atrás respecto a su &lt;em&gt;upstream&lt;/em&gt; &lt;code&gt;origin/pippin-merry&lt;/code&gt;; y ramas como &lt;code&gt;master&lt;/code&gt; que han divergido respecto a su &lt;em&gt;upstream&lt;/em&gt; &lt;code&gt;origin/master&lt;/code&gt;; también habrá ramas remotas que no serán seguidas por ninguna rama local o ramas locales que todavía no se han subido al repositorio remoto y que no tengan su equivalente en &lt;code&gt;origin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Y para terminar la introducción, algo muy importante: &lt;/p&gt;

&lt;blockquote&gt;


&lt;p&gt;🚨 &lt;strong&gt;No hay que editar nada que ya este en el repositorio remoto y que este siendo usado por otros desarrolladores, ya que se puede liar parda.&lt;/strong&gt;&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;Imagina que:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mortadelo hace &lt;code&gt;git push&lt;/code&gt; a &lt;code&gt;master&lt;/code&gt; con un commit que tiene un bug.&lt;/li&gt;
&lt;li&gt;Filemón se actualiza su rama con &lt;code&gt;master&lt;/code&gt;, obteniendo así el commit con el bug.&lt;/li&gt;
&lt;li&gt;Mortadelo se da cuenta de su error, y sin avisar a nadie: borra el commit con el bug de &lt;code&gt;master&lt;/code&gt;; intenta hacer &lt;code&gt;git push&lt;/code&gt; a &lt;code&gt;master&lt;/code&gt;, pero no puede por no se que error extraño; así que hace &lt;code&gt;git push -f&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Filemón integra su rama en &lt;code&gt;master&lt;/code&gt;, intenta subirla, y o bien vuelve a añadir a &lt;code&gt;master&lt;/code&gt; el commit que Mortadelo había borrado, o bien se encuentra con conflictos y tiene que perder un buen rato en resolverlos.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;El tener que usar &lt;code&gt;git push -f&lt;/code&gt; (o borrar la rama remota y volver a crearla con commits diferentes) es algo que debe hacer saltar todas las alarmas, y hacer pensar muy mucho si realmente es necesario o hay otras opciones.&lt;/p&gt;

&lt;p&gt;Dicho esto, si la rama es tuya, y estas seguro de que nadie más la ha usado ni ha usado ninguno de sus commits, es licito modificar los commits que hagan falta y usar &lt;code&gt;git push -f&lt;/code&gt;, porque a todos nos ha pasado que queramos cambiar algo que hemos subido por error.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git push -f&lt;/code&gt; es una herramienta más de Git, y si sigue hay después de tantos años por algo será, pero hay que usarla con mucho cuidado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trastear con repositorios remotos
&lt;/h2&gt;

&lt;p&gt;Personalmente, como más aprendo sobre las cosas es trasteando con ellas, y cómo más aprendí sobre los repositorios remotos de Git fue creándome un repositorio en local y clonándolo.&lt;br&gt;
En un minuto es posibles tener un área de pruebas donde ver como afectan los comando &lt;code&gt;git push&lt;/code&gt; y &lt;code&gt;git pull&lt;/code&gt; al repositorio remoto, crear situaciones para probar las cosas, probar cosas antes de aplicarlas al repositorio remoto de verdad, etc.&lt;br&gt;
También se puede crear un repositorio privado en GitHub o similares, pero me parece mucho más rápido y ágil probar en local.&lt;/p&gt;

&lt;p&gt;El proceso sería más o menos así&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Creo una carpeta donde poner los repositorios para las pruebas.&lt;/span&gt;
~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; sandbox/remotes 
~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;sandbox/remotes/

&lt;span class="c"&gt;# Creo una carpeta donde creare el repositorio remoto.&lt;/span&gt;
~/sandbox/remotes&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;origin
~/sandbox/remotes&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;origin/
&lt;span class="c"&gt;# Inicio el repositorio.&lt;/span&gt;
~/sandbox/remotes/origin&lt;span class="nv"&gt;$ &lt;/span&gt;git init
        Inicializado repositorio Git vacío en ~/sandbox/remotes/origin/.git/

&lt;span class="c"&gt;# Le añado algún commit.&lt;/span&gt;
~/sandbox/remotes/origin&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hola git"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; README.md
~/sandbox/remotes/origin&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
~/sandbox/remotes/origin&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"creado archivo index.html"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;master &lt;span class="o"&gt;(&lt;/span&gt;commit-raíz&lt;span class="o"&gt;)&lt;/span&gt; 246ceaf] creado archivo README.md
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
         create mode 100644 README.md
&lt;span class="c"&gt;# Me voy a otra rama para evitar los problemas del tipo&lt;/span&gt;
&lt;span class="c"&gt;# "remote: error: Por defecto, actualizar la rama actual &lt;/span&gt;
&lt;span class="c"&gt;# en un repositorio no vacío".&lt;/span&gt;
&lt;span class="c"&gt;# https://stackoverflow.com/a/2933656/1587302&lt;/span&gt;
~/sandbox/remotes/origin&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; no-editar

&lt;span class="c"&gt;# Voy atras.&lt;/span&gt;
~/sandbox/remotes/origin&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..

&lt;span class="c"&gt;# Clono el repositorio origin en la carpeta local.&lt;/span&gt;
~/sandbox/remotes&lt;span class="nv"&gt;$ &lt;/span&gt;git clone origin &lt;span class="nb"&gt;local 
        &lt;/span&gt;Clonando en &lt;span class="s1"&gt;'local'&lt;/span&gt;...
        hecho.

&lt;span class="c"&gt;# Entro en él y veo que tengo un clone de "origin".&lt;/span&gt;
~/sandbox/remotes&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd local&lt;/span&gt;/
~/sandbox/remotes&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout master
        Rama &lt;span class="s1"&gt;'master'&lt;/span&gt; configurada para hacer seguimiento a la rama remota &lt;span class="s1"&gt;'master'&lt;/span&gt; de &lt;span class="s1"&gt;'origin'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
        Cambiado a nueva rama &lt;span class="s1"&gt;'master'&lt;/span&gt;
~/sandbox/remotes/local&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama master
        Tu rama está actualizada con &lt;span class="s1"&gt;'origin/master'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio

~/sandbox/remotes/local&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;README.md 
        hola git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problemas al subir una rama
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Hago push pero lo cambios no se suben; al intentar hacer push sale un error; hago push pero no pasa nada; etc&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hay varios motivos por los que &lt;code&gt;git push&lt;/code&gt; puede dar error:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No se tienen permisos para escribir es un repositorio.
Por poner un ejemplo, es posible clonarse cualquier repositorio público de GitHub, pero al hacer &lt;code&gt;git push&lt;/code&gt; se obtendrá un error como este &lt;code&gt;remote: Permission to 30-seconds/30-seconds-of-code.git denied to Pepito.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;No se tienen permisos para escribir en una rama.
Es posible restringir los permisos de escritura a ramas sensibles como &lt;code&gt;master&lt;/code&gt;, de tal forma que sólo ciertos usuarios puedan escribir sobre ellas o solo se pueda escribir sobre ellas al darle a &lt;em&gt;Merge&lt;/em&gt; en las &lt;em&gt;"Pull request"&lt;/em&gt; o &lt;em&gt;"Merge request".&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Todavía no existe la rama remota.&lt;/li&gt;
&lt;li&gt;La rama local está detrás o no está al día con la rama remota&lt;/li&gt;
&lt;li&gt;La rama local ha divergido respecto a la rama remota y no es posible actualizarla.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para los dos primeros casos habrá que consultar al administrador del repositorio.&lt;/p&gt;

&lt;p&gt;En el tercer caso, &lt;code&gt;git push&lt;/code&gt; da error porque se le pide actualizar algo que no existe, y la solución es tan simple como crearla siguiendo las instrucciones que da Git en el mensaje de error.&lt;br&gt;
La siguientes veces que se ejecute &lt;code&gt;git push&lt;/code&gt; ya no se obtendrá el error, porque ya sabrá que debe actualizar.&lt;br&gt;
Aunque esto es algo que solo suelen experimentar los usuarios de consola, porque muchos muchos GUI por debajo controlan este caso y crean la rama remata si no existe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Intento hacer push de una rama que no existe y obtengo un error.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        fatal: La rama actual nueva-feature no tiene una rama upstream.
        Para realizar un push de la rama actual y configurar el remoto como upstream, use

            git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin nueva-feature

&lt;span class="c"&gt;# Así que la creo.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin HEAD
        Total 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/remotes/origin
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new branch]      HEAD -&amp;gt; nueva-feature
        Rama &lt;span class="s1"&gt;'nueva-feature'&lt;/span&gt; configurada para hacer seguimiento a la rama remota &lt;span class="s1"&gt;'nueva-feature'&lt;/span&gt; de &lt;span class="s1"&gt;'origin'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama nueva-feature
        Tu rama está actualizada con &lt;span class="s1"&gt;'origin/nueva-feature'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el ejemplo se utiliza &lt;code&gt;git push --set-upstream origin HEAD&lt;/code&gt; para crear la rama en lugar del comando sugerido por Git &lt;code&gt;git push --set-upstream origin nueva-feature&lt;/code&gt;.&lt;br&gt;
Es un pequeño atajo no tener que pensar en el nombre de la rama a la hora de crearla.&lt;/p&gt;

&lt;p&gt;Respecto a los dos últimos casos, si &lt;code&gt;git push&lt;/code&gt; da error, es importante hacer &lt;code&gt;git fetch&lt;/code&gt; para actualizar las ramas remotas, porque puede pasar que todo parezca estar en orden al ejecutar &lt;code&gt;git status&lt;/code&gt;, pero que no lo este porque otro desarrollador haya hecho cambios en el repositorio remoto desde la última vez se actualizo el repositorio local, y las referencias a las ramas remotas no estén actualizadas.&lt;/p&gt;

&lt;p&gt;Si la rama local está detrás de la rama remota no hay cambios que subir, y aunque el mensaje puede ser un poco agresivo es normal que no pase nada.&lt;br&gt;
Si se actualiza la rama seguirá sin pasar nada, pero el mensaje no será tan agresivo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Hago push y obtengo un mensaje un poco agresivo&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        To ~/sandbox/remotes/origin
         &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;rejected]        master -&amp;gt; master &lt;span class="o"&gt;(&lt;/span&gt;non-fast-forward&lt;span class="o"&gt;)&lt;/span&gt;
        error: falló el push de algunas referencias a &lt;span class="s1"&gt;'~/sandbox/remotes/origin'&lt;/span&gt;
        ayuda: Actualizaciones fueron rechazadas porque la punta de tu rama actual está
        ayuda: detrás de su contraparte remota. Integra los cambios remotos &lt;span class="o"&gt;(&lt;/span&gt;es decir
        ayuda: &lt;span class="s1"&gt;'git pull ...'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; antes de hacer push de nuevo.
        ayuda: Mira &lt;span class="s1"&gt;'Note about fast-forwards'&lt;/span&gt; en &lt;span class="s1"&gt;'git push --help'&lt;/span&gt; para más detalles.

&lt;span class="c"&gt;# Compruebo el estado y veo que mi rama se ha quedado detras&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama master
        Tu rama está detrás de &lt;span class="s1"&gt;'origin/master'&lt;/span&gt; por 1 commit, y puede ser avanzada rápido.
          &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git pull"&lt;/span&gt; para actualizar tu rama &lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# Actualizo la rama&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git pull
        Actualizando 246ceaf..47be068
        Fast-forward
         index.html | 1 +
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Y el git push segirá sin hacer nada, aunque el mensaje &lt;/span&gt;
&lt;span class="c"&gt;# no es tan agresivo&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        Everything up-to-date
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y si la rama remota y la rama local han evolucionado de manera distinta, es que han divergido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Compruebo el estado de la rama y veo que está por delante &lt;/span&gt;
&lt;span class="c"&gt;# de la rama remota, así que debería poder hacer push.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama master
        Tu rama está adelantada a &lt;span class="s1"&gt;'origin/master'&lt;/span&gt; por 1 commit.
          &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git push"&lt;/span&gt; para publicar tus commits locales&lt;span class="o"&gt;)&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# Pero falla.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        To sandbox/remotes/origin
         &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;rejected]        master -&amp;gt; master &lt;span class="o"&gt;(&lt;/span&gt;fetch first&lt;span class="o"&gt;)&lt;/span&gt;
        error: falló el push de algunas referencias a &lt;span class="s1"&gt;'sandbox/remotes/origin'&lt;/span&gt;
        ayuda: Actualizaciones fueron rechazadas porque el remoto contiene trabajo que
        ayuda: no existe localmente. Esto es causado usualmente por otro repositorio 
        ayuda: realizando push a la misma ref. Quizás quiera integrar primero los cambios
        ayuda: remotos &lt;span class="o"&gt;(&lt;/span&gt;ej. &lt;span class="s1"&gt;'git pull ...'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; antes de volver a hacer push.
        ayuda: Vea &lt;span class="s1"&gt;'Notes about fast-forwards0 en git push --help'&lt;/span&gt; para detalles.

&lt;span class="c"&gt;# Actualizo las ramas remotas y veo que la rama remota &lt;/span&gt;
&lt;span class="c"&gt;# se ha actualizado.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch 
        remote: Enumerando objetos: 5, listo.
        remote: Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        Desempaquetando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 277 bytes | 277.00 KiB/s, listo.
        Desde sandbox/remotes/origin
           246ceaf..792a7bf  master     -&amp;gt; origin/master

&lt;span class="c"&gt;# Intento obtener información más concreta y veo que &lt;/span&gt;
&lt;span class="c"&gt;# las ramas han divergido.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama master
        Tu rama y &lt;span class="s1"&gt;'origin/master'&lt;/span&gt; han divergido,
        y tienen 1 y 1 commits diferentes cada una respectivamente.
          &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git pull"&lt;/span&gt; para fusionar la rama remota en la tuya&lt;span class="o"&gt;)&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8i9b5g4585yvdy0e5ouc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8i9b5g4585yvdy0e5ouc.png" alt="rama divergente"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el ejemplo se puede ver que la rama local &lt;code&gt;master&lt;/code&gt; y la rama remota &lt;code&gt;origin/master&lt;/code&gt; partieron de commit &lt;code&gt;creado archivo index.html&lt;/code&gt; y que en ambas se han hecho commits.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git push&lt;/code&gt; solo funciona cuando los commits que se suben salen del último commit de la rama remota, es decir, se produce un &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#git-merge-ese-comando-problem%C3%A1tico"&gt;fast forward&lt;/a&gt;, en caso contrario falla y habrá que actualizar la rama local con el &lt;em&gt;upstream&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;La forma de salir del paso depende de &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#c%C3%B3mo-integrar-una-rama"&gt;como se integren&lt;/a&gt; las ramas en el proyecto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si se usan rebases, el comando sería &lt;code&gt;git rebase &amp;lt;upstream&amp;gt;&lt;/code&gt;, por ejemplo &lt;code&gt;git rebase origin/master&lt;/code&gt; si por ejemplo mi el &lt;em&gt;upstream&lt;/em&gt; es &lt;code&gt;origin/master&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si se usan merges &lt;code&gt;git pull&lt;/code&gt; .&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Una vez integrada, y si no se da la casualidad de que justo se ha vuelto a actualizar la rama remota entre medias, se podrá hacer &lt;code&gt;git push&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modificar algo en el repositorio remoto
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;He visto después de hacer push que el mensaje de un commit tiene una errata; he mergeado la rama que no era y he hecho push; he subido algo por error; me acabo de dar cuenta de que he subido un bug; etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Como se vio en la introducción&lt;/p&gt;

&lt;blockquote&gt;


&lt;p&gt;🚨 &lt;strong&gt;No hay que editar nada que ya este en el repositorio remoto y que este siendo usado por otros desarrolladores, ya que se puede liar parda.&lt;/strong&gt;&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;Pero ¿quién no la ha cometido errores alguna vez?&lt;/p&gt;

&lt;p&gt;Como también se dijo en la introducción, si la rama es tuya, y estas seguro de que nadie más la ha usado ni ha usado ninguno de sus commits, es licito modificar los commits que hagan falta y usar &lt;code&gt;git push -f&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"Hañado titúlo"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;mi-rama 13c9acf] Hañado titúlo
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        Enumerando objetos: 5, listo.
        Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Compresión delta usando hasta 12 hilos
        Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;2/2&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Escribiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 314 bytes | 314.00 KiB/s, listo.
        Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To sandbox/remotes/origin
           207ba5a..13c9acf  mi-rama -&amp;gt; mi-rama

&lt;span class="c"&gt;# Me doy cuenta de que he metido algunos errores en el mensaje &lt;/span&gt;
&lt;span class="c"&gt;# y los corrijo.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git amend &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Añado título"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;mi-rama ec27a36] Añado título
         Date: Sat May 8 21:05:27 2021 +0200
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Pero el push falla porque he modificado un commit que &lt;/span&gt;
&lt;span class="c"&gt;# ya estaba en el repositorio remoto.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        To sandbox/remotes/origin
         &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;rejected]        mi-rama -&amp;gt; mi-rama &lt;span class="o"&gt;(&lt;/span&gt;non-fast-forward&lt;span class="o"&gt;)&lt;/span&gt;
        error: falló el push de algunas referencias a &lt;span class="s1"&gt;'sandbox/remotes/origin'&lt;/span&gt;
        ayuda: Actualizaciones fueron rechazadas porque la punta de tu rama actual está
        ayuda: detrás de su contraparte remota. Integra los cambios remotos &lt;span class="o"&gt;(&lt;/span&gt;es decir
        ayuda: &lt;span class="s1"&gt;'git pull ...'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; antes de hacer push de nuevo.
        ayuda: Mira &lt;span class="s1"&gt;'Note about fast-forwards'&lt;/span&gt; en &lt;span class="s1"&gt;'git push --help'&lt;/span&gt; para más detalles.

&lt;span class="c"&gt;# Compruebo el estado.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama mi-rama
        Tu rama y &lt;span class="s1"&gt;'origin/mi-rama'&lt;/span&gt; han divergido,
        y tienen 1 y 1 commits diferentes cada una respectivamente.
          &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git pull"&lt;/span&gt; para fusionar la rama remota en la tuya&lt;span class="o"&gt;)&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# Estando muy muy seguro de que no va a afectar a otras personas.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;-f&lt;/span&gt;
        Enumerando objetos: 5, listo.
        Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Compresión delta usando hasta 12 hilos
        Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;2/2&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Escribiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 318 bytes | 318.00 KiB/s, listo.
        Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/remotes/origin
         + 13c9acf...ec27a36 mi-rama -&amp;gt; mi-rama &lt;span class="o"&gt;(&lt;/span&gt;forced update&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama mi-rama
        Tu rama está actualizada con &lt;span class="s1"&gt;'origin/mi-rama'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si el &lt;code&gt;git push&lt;/code&gt; se hizo a una rama compartida, las acciones a tomar dependen de la situación:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si los commits son para corregir una errata en un mensaje, lo mejor es dejarlo correr, porque arreglarlo no merece la pena.&lt;/li&gt;
&lt;li&gt;Si es algo que hay que deshacer, lo más correcto sería usar &lt;code&gt;git revert&lt;/code&gt; para revertir un &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#revertir-commit"&gt;commit individual&lt;/a&gt; o un &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#deshacer-un-merge"&gt;merge commit&lt;/a&gt;, probar bien los cambios, y después hacer &lt;code&gt;git push&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si es algo como un bug, siempre se pueden hacer commits para corregirlo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aunque lo más correcto no siempre es lo más cómodo, para que mentir. &lt;br&gt;
Si se ha hecho &lt;code&gt;git push&lt;/code&gt; a una rama compartida con otros desarrolladores y ninguno ha usado ninguno de los commits que se han subido (no han hecho &lt;code&gt;git pull&lt;/code&gt; en la rama comprometida, ni &lt;code&gt;git pull origin &amp;lt;rama&amp;gt;&lt;/code&gt;, ni &lt;code&gt;git cherry-pick&lt;/code&gt; de ninguno de los commits) se puede:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avisar al resto de desarrolladores de que se ha subido algo por error y que hasta nuevo aviso no hagan ni &lt;code&gt;git pull&lt;/code&gt; en la rama, &lt;code&gt;git pull origin &amp;lt;rama&amp;gt;&lt;/code&gt; ni &lt;code&gt;git cherry-pick&lt;/code&gt; de los commits recién subidos.&lt;/li&gt;
&lt;li&gt;Hacer lo cambios que se tengan que hacer y hacer &lt;code&gt;git push -f&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pedir al resto de desarrolladores que se actualicen las ramas remotas con &lt;code&gt;git fetch&lt;/code&gt; y decir que ya se puede trabajar con normalidad.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;¿Y si algún otro desarrollador ya ha hecho uso de alguno de los commits subidos?&lt;br&gt;
Siempre es posible seguir los pasos de arriba y que el resto de desarrolladores rehagan parte del trabajo, pero igual es demasiado trastorno y no merece la pena.&lt;/p&gt;

&lt;p&gt;¿Y si se ha modificado algún commit en local y se decide que lo mejor es dar marcha atrás porque no se puede hacer &lt;code&gt;git push -f&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Se puede volver a lo que había antes de modificar el commit siguiendo los mismos pasos que para &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#recuperar-una-rama-borrada-por-error"&gt;recuperar una rama borrada por error&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Git pull, ese comando problemático
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"git pull" cada vez hace una cosa distinta; después de hacer "git pull" la aplicación ya no funciona.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt; sirve para actualizar una rama local con una rama del repositorio remoto. &lt;br&gt;
Por debajo primero hace &lt;code&gt;git fetch&lt;/code&gt; , actualizando todas las ramas del repositorio remoto, y después a &lt;code&gt;git merge &amp;lt;rama-remota&amp;gt;&lt;/code&gt; .&lt;br&gt;
Ciertamente es muy cómodo, pero hay que tener todas las &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#git-merge-ese-comando-problem%C3%A1tico"&gt;consideraciones que al mergear una rama&lt;/a&gt; (pueden surgir conflictos, hay revisar que todo sigue funcionando después de un merge commit, etc) y alguna más.&lt;/p&gt;

&lt;p&gt;La forma más verbosa de invocar a &lt;code&gt;git pull&lt;/code&gt; sería &lt;code&gt;git pull origin &amp;lt;rama&amp;gt;&lt;/code&gt;, que por debajo vendría a hacer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git fetch origin&lt;/code&gt; , que actualizaría todas las ramas remotas (las ramas &lt;code&gt;origin/&amp;lt;rama&amp;gt;&lt;/code&gt; que se mencionaban en la introducción).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git merge origin/&amp;lt;rama&amp;gt;&lt;/code&gt; para mergear la rama remota &lt;code&gt;origin/&amp;lt;rama&amp;gt;&lt;/code&gt; en la rama local.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es una forma muy útil para por ejemplo actualizar la rama local en la que se está desarrollando una nueva feature con la última versión de &lt;code&gt;master&lt;/code&gt; en el repositorio remoto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama mi-feature
        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# Actualizo mi-feature con la rama master del repositorio remoto.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git pull origin master 

        &lt;span class="c"&gt;# Internamente hace git fetch.&lt;/span&gt;
        remote: Enumerando objetos: 5, listo.
        remote: Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;2/2&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        Desempaquetando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 291 bytes | 291.00 KiB/s, listo.

        &lt;span class="c"&gt;# La rama master ha cambiado en el repositorio remoto&lt;/span&gt;
        &lt;span class="c"&gt;# así que actualiza origin/master.&lt;/span&gt;
        Desde ~/sandbox/remotes/origin
         &lt;span class="k"&gt;*&lt;/span&gt; branch            master     -&amp;gt; FETCH_HEAD
           792a7bf..1a16ce3  master     -&amp;gt; origin/master

        &lt;span class="c"&gt;# Hace el merge.&lt;/span&gt;
        Merge made by the &lt;span class="s1"&gt;'recursive'&lt;/span&gt; strategy.
         index.html | 2 ++
         1 file changed, 2 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Reviso la el úlitmo commit para ver que ha sido un merge.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt;
        commit 73365ef70d893c3b3b9680e0676bda0c78c36505 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; mi-feature&lt;span class="o"&gt;)&lt;/span&gt;
        Merge: 504b167 1a16ce3

            Merge branch &lt;span class="s1"&gt;'master'&lt;/span&gt; of ~/sandbox/remotes/origin into mi-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otra forma es &lt;code&gt;git pull&lt;/code&gt; a secas, bastante útil para actualizar la rama local con el &lt;em&gt;upstream&lt;/em&gt;.&lt;br&gt;
Por debajo vendría a hacer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git fetch &amp;lt;remoto&amp;gt;&lt;/code&gt;, donde &lt;code&gt;&amp;lt;remoto&amp;gt;&lt;/code&gt; sería el repositorio remoto del &lt;em&gt;upstream&lt;/em&gt; (si el &lt;em&gt;upstream&lt;/em&gt; fuese &lt;code&gt;origin/master&lt;/code&gt; haría &lt;code&gt;git fetch origin&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git merge &amp;lt;upstream&amp;gt;&lt;/code&gt;, para mergear el &lt;em&gt;upstream&lt;/em&gt; en la rama local (si el &lt;em&gt;upstream&lt;/em&gt; fuese &lt;code&gt;origin/master&lt;/code&gt; haría &lt;code&gt;git merge master&lt;/code&gt;).
Si la rama no tuviese &lt;em&gt;upstream&lt;/em&gt; indicaría como añadirlo.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Hago git status y veo que no estoy siguiendo &lt;/span&gt;
&lt;span class="c"&gt;# a ninguna rama remota.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama mi-feature
        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# git pull hace internamente el git fetch, y luego falla, &lt;/span&gt;
&lt;span class="c"&gt;# porque la rama actual no sigue a ninguna rama remota&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git pull
        remote: Enumerando objetos: 5, listo.
        remote: Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;2/2&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        Desempaquetando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 290 bytes | 290.00 KiB/s, listo.
        Desde ~/sandbox/remotes/origin
           792a7bf..01d5c54  master     -&amp;gt; origin/master
        No hay información de rastreo para la rama actual.
        Por favor especifica a qué rama quieres fusionar.
        Ver git-pull&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt; para detalles.

            git pull &amp;lt;remoto&amp;gt; &amp;lt;rama&amp;gt;

        Si deseas configurar el rastreo de información para esta rama, puedes hacerlo con:

            git branch &lt;span class="nt"&gt;--set-upstream-to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;origin/&amp;lt;rama&amp;gt; mi-feature

&lt;span class="c"&gt;# Cambio a otra rama que si sigue a una rama remota.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout master 
        Cambiado a rama &lt;span class="s1"&gt;'master'&lt;/span&gt;
        Tu rama está detrás de &lt;span class="s1"&gt;'origin/master'&lt;/span&gt; por 1 commit, y puede ser avanzada rápido.
          &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git pull"&lt;/span&gt; para actualizar tu rama &lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Hago git pull.&lt;/span&gt;
&lt;span class="c"&gt;# Internamente hace el git fecth, pero como no hay cambios&lt;/span&gt;
&lt;span class="c"&gt;# en el repositorio remoto no imprime nada.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git pull
        Actualizando 792a7bf..01d5c54
        Fast-forward
         index.html | 1 +
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Todas las opciones que se pueden aplicar a &lt;code&gt;git merge&lt;/code&gt; se pueden aplicar también a &lt;code&gt;git pull&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si por ejemplo se está en la rama &lt;code&gt;master&lt;/code&gt; y se quiere actualizar con el repositorio remoto puede ser útil ejecutar &lt;code&gt;git pull --ff-only&lt;/code&gt; ; haciéndolo así &lt;code&gt;git pull&lt;/code&gt; fallaría si las ramas han divergido, evitando así que la rama &lt;code&gt;master&lt;/code&gt; se diferente a la de otros desarrolladores.&lt;/p&gt;

&lt;p&gt;Se puede ejecutar &lt;code&gt;git pull --no-ff --no-commit origin hotfix&lt;/code&gt; para que si el merge resultase en un &lt;em&gt;merge commit&lt;/em&gt; tener la posibilidad de revisar los cambios antes de completar el commit, por si hubiese alguna incompatibilidad entre las dos ramas. &lt;/p&gt;
&lt;h2&gt;
  
  
  Renombrar una rama
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Corregir un texto incorrecto, se copio la clave del issute tracker que no era, etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Las acciones para renombrar ramas solo renombran ramas locales, no actúan sobre los &lt;em&gt;upstream&lt;/em&gt;; como tal no existe la opción de renombrar una rama en un repositorio remoto, aunque si se puede borrar la rama con el nombre antiguo y crear una rama con el nombre nuevo. Adicionalmente habría que actualizar el &lt;em&gt;upstream&lt;/em&gt; de la rama, porque no se actualiza solo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Hago un git status y veo que estoy en la rama dovolop &lt;/span&gt;
&lt;span class="c"&gt;# y que estoy siguiendo a la rama remota origin/dovolop.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama dovolop
        Tu rama está actualizada con &lt;span class="s1"&gt;'origin/dovolop'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# Otra opción para ver esto es mirarlo es &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; dovolop                d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/dovolop] crear hoja de estilos home.css
          master                 d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/master] crear hoja de estilos home.css
          remotes/origin/dovolop d63cc7b crear hoja de estilos home.css
          remotes/origin/master  d63cc7b crear hoja de estilos home.css

&lt;span class="c"&gt;# El nombre debería ser develop, así que renombro la rama.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-m&lt;/span&gt; develop

&lt;span class="c"&gt;# Si verifico el estado veo que he renombrado la rama local, &lt;/span&gt;
&lt;span class="c"&gt;# pero no la remota, y que mi rama local todavía sigue &lt;/span&gt;
&lt;span class="c"&gt;# a origin/dovolop.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-vv&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; develop                d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/dovolop] crear hoja de estilos home.css
          master                 d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/master] crear hoja de estilos home.css
          remotes/origin/dovolop d63cc7b crear hoja de estilos home.css
          remotes/origin/master  d63cc7b crear hoja de estilos home.css

&lt;span class="c"&gt;# "Actualizo" la rama remota borrando la vieja y creando la nueva.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push origin :dovolop develop
        Total 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/git
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         dovolop
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new branch]      develop -&amp;gt; develop

&lt;span class="c"&gt;# Si consulto el estado veo que la rama remota se ha renombrado&lt;/span&gt;
&lt;span class="c"&gt;# y que mi rama local sigue a una rama "desaparecida" o "gone".&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-vv&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; develop                d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/dovolop: desaparecido] crear hoja de estilos home.css
          master                 d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/master] crear hoja de estilos home.css
          remotes/origin/develop d63cc7b crear hoja de estilos home.css
          remotes/origin/master  d63cc7b crear hoja de estilos home.css

&lt;span class="c"&gt;# Así que tengo que actualizar el upstream para que siga &lt;/span&gt;
&lt;span class="c"&gt;# a la rama renombrada.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin develop 
        Rama &lt;span class="s1"&gt;'develop'&lt;/span&gt; configurada para hacer seguimiento a la rama remota &lt;span class="s1"&gt;'develop'&lt;/span&gt; de &lt;span class="s1"&gt;'origin'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
        Everything up-to-date

&lt;span class="c"&gt;# Y ya está todo en orden.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-vv&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; develop                d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/develop] crear hoja de estilos home.css
          master                 d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/master] crear hoja de estilos home.css
          remotes/origin/develop d63cc7b crear hoja de estilos home.css
          remotes/origin/master  d63cc7b crear hoja de estilos home.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;


&lt;p&gt;🚨 &lt;strong&gt;Los comandos anteriores pueden afectar a otros desarrolladores.&lt;/strong&gt;&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;Si el Filemón tenía una rama siguiendo a &lt;code&gt;dovolop&lt;/code&gt; y Mortadelo la "renombra" en el repositorio remoto, pueden ocurrir varias cosas: que Filemón no sea capaz de actualizarse con los commits que haga Mortadelo, ya que ha perdido la referencia la rama remota; o que Filemón haga nuevos commits y al subirlos al repositorio remoto cree una nueva sin darse cuenta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Mortadelo comprueba el estado de las ramas.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; dovolop                d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/dovolop] crear hoja de estilos home.css
          master                 d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/master] crear hoja de estilos home.css
          remotes/origin/dovolop d63cc7b crear hoja de estilos home.css
          remotes/origin/master  d63cc7b crear hoja de estilos home.css

&lt;span class="c"&gt;# Hace un fetch y no le presta mucha antención, porque &lt;/span&gt;
&lt;span class="c"&gt;# no es extraño que se creen o borren ramas.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch 
        Desde ~/sandbox/git
         - &lt;span class="o"&gt;[&lt;/span&gt;eliminado]       &lt;span class="o"&gt;(&lt;/span&gt;nada&lt;span class="o"&gt;)&lt;/span&gt;     -&amp;gt; origin/dovolop
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;nueva rama]      develop    -&amp;gt; origin/develop

&lt;span class="c"&gt;# Si Filemón comprobase el estado de la rama vería algo raro, &lt;/span&gt;
&lt;span class="c"&gt;# pero supongamos que no lo hace.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; dovolop                d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/dovolop: desaparecido] crear hoja de estilos home.css
          feature                d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/feature: desaparecido] crear hoja de estilos home.css
          master                 d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/master] crear hoja de estilos home.css
          remotes/origin/develop d63cc7b crear hoja de estilos home.css
          remotes/origin/master  d63cc7b crear hoja de estilos home.css

&lt;span class="c"&gt;# Hace algunos cambios y los commitea.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"algunos cambios"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;dovolop 190e822] algunos cambios
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Sube el nuevo commit al repositorio remoto...&lt;/span&gt;
&lt;span class="c"&gt;# y ve que se ha creado una nueva rama, aunque el esperaba &lt;/span&gt;
&lt;span class="c"&gt;# que se hubiese actualizado la rama dovolop&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        Enumerando objetos: 5, listo.
        Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Compresión delta usando hasta 12 hilos
        Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Escribiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 305 bytes | 305.00 KiB/s, listo.
        Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 1&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/git
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new branch]      dovolop -&amp;gt; dovolop

&lt;span class="c"&gt;# Y sin darse cuenta ha recreado la rama que mi Mortadelo &lt;/span&gt;
&lt;span class="c"&gt;# con tanto esfuerzo renombro.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-vv&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; dovolop                190e822 &lt;span class="o"&gt;[&lt;/span&gt;origin/dovolop] algunos cambios
          master                 d63cc7b &lt;span class="o"&gt;[&lt;/span&gt;origin/master] crear hoja de estilos home.css
          remotes/origin/develop d63cc7b crear hoja de estilos home.css
          remotes/origin/dovolop 190e822 algunos cambios
          remotes/origin/master  d63cc7b crear hoja de estilos home.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mantener el entorno limpio: cuando las ramas no dejan ver el bosque
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"git branch" y tengo muchas ramas que ya no se usan; "git branch -a " muestra ramas del repositorio remoto que ya fueron borradas; "git status" dice que el upstream ha desaparecido o "is gone".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;En repositorios muy activos y con muchos desarrolladores es fácil que &lt;code&gt;git branch&lt;/code&gt; y &lt;code&gt;git brach -a&lt;/code&gt; devuelvan decenas de resultados, de los cuales la inmensa mayoría serán ramas que no se han usado en meses.&lt;br&gt;
Git nunca borra nada a menos que se le diga explícitamente, lo cual esta bien porque nunca se pierde información, pero tiene la contra de que se puede acabar con información que ya no es relevante y que dificulta encontrar lo que se esta buscando, como cuando se tiene el escritorio tan lleno de archivos, carpetas y enlaces directos que lleva un rato encontrar algo que no uses todos los días.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ramas del repositorio remoto que ya no existen
&lt;/h3&gt;

&lt;p&gt;Las más fáciles de limpiar son las ramas remotas que ya no existen en el repositorio remoto, es decir aquellas que cuando:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pin subió la rama &lt;code&gt;feature/tiger&lt;/code&gt; al repositorio remeto.&lt;/li&gt;
&lt;li&gt;Pon hizo un &lt;code&gt;git fetch&lt;/code&gt;, el cual creo la rama &lt;code&gt;origin/feature/tiger&lt;/code&gt;.
Si ejecutase hiciese &lt;code&gt;git branch -a&lt;/code&gt; mostraría, entre otras, &lt;code&gt;origin/feature/tiger&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pin borro &lt;code&gt;feature/tiger&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pon hizo &lt;code&gt;git fetch&lt;/code&gt;, que no cambio nada.
Si ejecutase hiciese &lt;code&gt;git branch -a&lt;/code&gt; seguiría mostrando &lt;code&gt;origin/feature/tiger&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Se le puede indicar a Git que borre esas ramas llamando a &lt;code&gt;git fetch&lt;/code&gt; o a &lt;code&gt;git pull&lt;/code&gt; con la opción &lt;code&gt;--prune&lt;/code&gt;, para indicar que tiene que &lt;em&gt;podar&lt;/em&gt; las ramas que ya no existen.&lt;br&gt;
Si se usa un GUI, puede que ya haga el &lt;em&gt;prune&lt;/em&gt; automáticamente, o puede que tenga una opción para configurarlo.&lt;/p&gt;

&lt;p&gt;Es posible configurar Git para que por defecto haga &lt;em&gt;prune&lt;/em&gt; , ahorrando así tener que usar la opción &lt;code&gt;--prune&lt;/code&gt; en cada llamada, para ello, añadir lo siguiente al archivo &lt;code&gt;~/.gitconfig&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;fetch]
        prune &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un ejemplo paso a paso&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;### Pin publica la rama feature/tiger.&lt;/span&gt;

&lt;span class="c"&gt;# Pon hace un fetch.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch 
        remote: Enumerando objetos: 5, listo.
        remote: Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;2/2&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        Desempaquetando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 294 bytes | 294.00 KiB/s, listo.
        Desde ~/sandbox/remotes/origin
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;nueva rama]      feature/tiger -&amp;gt; origin/feature/tiger

&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; master
          remotes/origin/HEAD -&amp;gt; origin/master
          remotes/origin/feature/tiger
          remotes/origin/master

&lt;span class="c"&gt;### Pin borra del repositorio remoto feature/tiger.&lt;/span&gt;

&lt;span class="c"&gt;# Pon hago un fecth y no pasa nada.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch 

&lt;span class="c"&gt;# La rama origin/feature/tiger sigue existiendo.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; master
          remotes/origin/HEAD -&amp;gt; origin/master
          remotes/origin/feature/tiger
          remotes/origin/master

&lt;span class="c"&gt;# Si hiciese fetch con la opción --prune&lt;/span&gt;
&lt;span class="c"&gt;# origin/feature/tiger se borraría.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch &lt;span class="nt"&gt;--prune&lt;/span&gt;
        Desde ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;eliminado]       &lt;span class="o"&gt;(&lt;/span&gt;nada&lt;span class="o"&gt;)&lt;/span&gt;     -&amp;gt; origin/feature/tiger

&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt; master
          remotes/origin/HEAD -&amp;gt; origin/master
          remotes/origin/master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ramas locales que se han quedado sin rama remota
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Pin subió la rama &lt;code&gt;feature/duck&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pon hizo un &lt;code&gt;git fech&lt;/code&gt; y &lt;code&gt;git checkout feature/duck&lt;/code&gt;, lo cual creo la rama local &lt;code&gt;feature/duck&lt;/code&gt; cuyo &lt;em&gt;upstream&lt;/em&gt; es &lt;code&gt;origin/feature/duck&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pin mergeó &lt;code&gt;feature/duck&lt;/code&gt; en master y la borro del repositorio remoto para no deja una rama que ya terminado su ciclo de vida.&lt;/li&gt;
&lt;li&gt;Pon hizo &lt;code&gt;git fecth&lt;/code&gt; con la opción de &lt;em&gt;autoprune&lt;/em&gt;, con lo cual Git borro la rama &lt;code&gt;origin/feature/duck&lt;/code&gt; , pero no &lt;code&gt;feature/duck&lt;/code&gt;, no vaya a ser que por alguna razón se quiera conservar en local, o que la rama local hubiese divergido de la rama remota y se pierdan commits.&lt;/li&gt;
&lt;li&gt;Pon ejecuta &lt;code&gt;git status&lt;/code&gt; y ve el siguiente mensaje
&lt;em&gt;Tu rama está basada en 'origin/feature/duck', pero upstream ha desaparecido.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La manera de limpiar estar ramas es &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#recuperar-una-rama-borrada-por-error"&gt;borrarlas a mano&lt;/a&gt;: &lt;code&gt;git branch -d feature/duck&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pero con el tiempo se vuelve una tarea repetitiva y pesada, sobre todo cuando hay varias ramas en ese estado.&lt;/p&gt;

&lt;p&gt;Una forma de hacerlo menos pesado es definiendo un par de alias en &lt;code&gt;~/.gitconfig&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pruned&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;branches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"!f() { git branch -vv | grep -E ': (desaparecido|gone)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;]' | grep -v '*' | awk '{print $1}' | xargs -r git branch -d; }; f"&lt;/span&gt;
  &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;'git&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pruned&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;branches&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;git clear-pruned-branches&lt;/code&gt; borraría las ramas desaparecidas que no estén mergeadas en la rama actual (&lt;code&gt;git branch -d&lt;/code&gt;). &lt;br&gt;
Si alguna rama no se puede borrar porque no está mergeada mostrará un mensaje tal que &lt;em&gt;&lt;code&gt;error: La rama 'feature/gorilla' no ha sido fusionada completamente.&lt;/code&gt;&lt;/em&gt;, y tal vez haya que prestarle un poco más de atención para no borrar algún commit que se olvido subir.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git fetch-and-clear&lt;/code&gt; serviría como atajo para evitar tener que escribir &lt;code&gt;git fecth &amp;amp;&amp;amp; git clear-pruned-branches&lt;/code&gt;.&lt;br&gt;
Para mantener el sistema limpio se puede usar &lt;code&gt;git clear-pruned-branches&lt;/code&gt; o usar &lt;code&gt;git fetch-and-clear&lt;/code&gt; en lugar de &lt;code&gt;git fetch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Un ejemplo paso a paso&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;### Pin publica la rama feature/duck.&lt;/span&gt;

&lt;span class="c"&gt;# Pon hace un fetch y va a la ramara a cotillear.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch
        Desde ~/sandbox/remotes/origin
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;nueva rama]      duck       -&amp;gt; origin/duck
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout duck 
        Rama &lt;span class="s1"&gt;'duck'&lt;/span&gt; configurada para hacer seguimiento a la rama remota &lt;span class="s1"&gt;'duck'&lt;/span&gt; de &lt;span class="s1"&gt;'origin'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
        Cambiado a nueva rama &lt;span class="s1"&gt;'duck'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama duck
        Tu rama está actualizada con &lt;span class="s1"&gt;'origin/duck'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;### Pin borra del repositorio remoto feature/duck.&lt;/span&gt;

&lt;span class="c"&gt;# Pon hace un fecth y como tiene el autoprune activo &lt;/span&gt;
&lt;span class="c"&gt;# borra la rama remota.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch
        Desde ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;eliminado]       &lt;span class="o"&gt;(&lt;/span&gt;nada&lt;span class="o"&gt;)&lt;/span&gt;     -&amp;gt; origin/duck

&lt;span class="c"&gt;# git status dice que el upstream ha desaparecido.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
        En la rama duck
        Tu rama está basada en &lt;span class="s1"&gt;'origin/duck'&lt;/span&gt;, pero upstream ha desaparecido.
          &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git branch --unset-upstream"&lt;/span&gt; para arreglar&lt;span class="o"&gt;)&lt;/span&gt;

        nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# Para borrarla tendría que ir a otra rama y borrarla&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout master 
        Cambiado a rama &lt;span class="s1"&gt;'master'&lt;/span&gt;
        Tu rama está actualizada con &lt;span class="s1"&gt;'origin/master'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-d&lt;/span&gt; duck
        Eliminada la rama duck &lt;span class="o"&gt;(&lt;/span&gt;era 01d5c54&lt;span class="o"&gt;)&lt;/span&gt;..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ramas remotas que han sido mergeadas pero no borradas
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Pin subió la rama &lt;code&gt;feature/dolphin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Mergeó la rama &lt;code&gt;feature/dolphine&lt;/code&gt; en &lt;code&gt;master&lt;/code&gt; pero no la borro.&lt;/li&gt;
&lt;li&gt;La rama sigue ahí 3 meses después.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Muchos sistemas de control de versiones como GitHub o Bitbucket tienen una opción para borrar la rama al mergear si se usan &lt;em&gt;Pull Request&lt;/em&gt; o &lt;em&gt;Merge Request&lt;/em&gt;, pero no es raro que se olvide marcarla, o que el merge se haga en local y se olvide borrar la rama después.&lt;/p&gt;

&lt;p&gt;Una solución es ir al repositorio remoto y borrar una por una, asegurándose de borrar solo las ramas mergeadas para no perder ningún commit&lt;br&gt;
Pero de nuevo es una tarea manual y tediosa, que se puede simplificar con un comando de consola&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ir a la rama de integración, master en ese caso&lt;/span&gt;
git checkout master &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Actualizarla a la última versión` \&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git pull &lt;span class="nt"&gt;--ff-only&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Listar todas ramas remotas mergeadas en master` \&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git branch &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--merged&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Excluir del listado las ramas que no hay que borrar;` \&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# con expresiones regulares se exluyen las que contienen el texto` \&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# "master", "production" o "RC"` \&lt;/span&gt;
    | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-vE&lt;/span&gt; &lt;span class="s1"&gt;'master|production|RC'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Quitar del texto el nombre del repositorio remoto` \&lt;/span&gt;
  | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/origin\///'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Borrar las ramas del repositorio remoto` \&lt;/span&gt;
  | xargs &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 git push &lt;span class="nt"&gt;--delete&lt;/span&gt; origin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No es un comando precisamente sencillo, y personalmente siempre me da un poco de respecto ejecutarlo.&lt;br&gt;
Por ello, primero listo las ramas que se irían a borrar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ir a la rama de integración, master en ese caso&lt;/span&gt;
git checkout master &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Actualizarla a la última versión` \&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git pull &lt;span class="nt"&gt;--ff-only&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Listar todas ramas remotas mergeadas en master` \&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git branch &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--merged&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Excluir del listado las ramas que no hay que borrar` \&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# con expresiones regulares se exluyen las que contienen el texto` \&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# "master", "production" o "RC"` \&lt;/span&gt;
    | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-vE&lt;/span&gt; &lt;span class="s1"&gt;'master|production|RC'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Quitar del texto el nombre del repositorio remoto` \&lt;/span&gt;
  | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/origin\///'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las reviso, y si todo me cuadra ya lanzo el comando completo.&lt;/p&gt;

&lt;p&gt;Y como medida de seguridad adicional, siempre se puede clonar el proyecto original para tener un backup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repository-url&amp;gt; &amp;lt;project-name&amp;gt;-bck-&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Hago 'git branch' y veo que hay muchas ramas,&lt;/span&gt;
&lt;span class="c"&gt;# muchas de las cuales creo que ya no se usan.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch 
        &lt;span class="k"&gt;*&lt;/span&gt; contenido-home
          master
          rama-dos
          rama-nueve
          rama-seis
          rama-siete
          rama-tres
          rama-uno
          seccion-contacto

&lt;span class="c"&gt;# Intento borrar alguna que ya se haya borrado del repositorio &lt;/span&gt;
&lt;span class="c"&gt;# remoto,pero nada.&lt;/span&gt;
&lt;span class="c"&gt;# (fetch-and-clear es un alias descrito algo más arriba en &lt;/span&gt;
&lt;span class="c"&gt;# "Ramas locales que se han quedado sin rama remota")&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch-and-clear

&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout master 
&lt;span class="c"&gt;# Miro cuantas ramas hay mergeadas en master y hay unas cuantas...&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--merged&lt;/span&gt;
        origin/HEAD -&amp;gt; origin/master
      origin/master
      origin/production
      origin/rama-cinco
      origin/rama-cuatro
      origin/rama-diez
      origin/rama-dos
      origin/rama-nueve
      origin/rama-ocho
      origin/rama-seis
      origin/rama-siete
      origin/rama-tres
      origin/rama-uno
      origin/seccion-contacto

&lt;span class="c"&gt;# Asi que quiero borrarlas todas menos 'production'. &lt;/span&gt;
&lt;span class="c"&gt;# Como borrarlas una a una sería demasiado tedioso uso un script.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--merged&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Excluir del listado las ramas que no hay que borrar;` \&lt;/span&gt;
   &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# con expresiones regulares se exluyen las que contienen el texto` \&lt;/span&gt;
   &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# "master", "production" o "RC"` \&lt;/span&gt;
   | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-vE&lt;/span&gt; &lt;span class="s1"&gt;'master|production|RC'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Quitar del texto el nombre del repositorio remoto` \&lt;/span&gt;
   | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/origin\///'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Borrar las ramas del repositorio remoto` \&lt;/span&gt;
   | xargs &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 git push &lt;span class="nt"&gt;--delete&lt;/span&gt; origin
                To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-cinco
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-cuatro
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-diez
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-dos
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-nueve
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-ocho
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-seis
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-siete
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-tres
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         rama-uno
        To ~/sandbox/remotes/origin
         - &lt;span class="o"&gt;[&lt;/span&gt;deleted]         seccion-contacto

&lt;span class="c"&gt;# Listo todas las ramas y veo que se han borrado muchas &lt;/span&gt;
&lt;span class="c"&gt;# del repositorio remoto, pero todavía quedan muchas en local. &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt;
          contenido-home
        &lt;span class="k"&gt;*&lt;/span&gt; master
          rama-dos
          rama-nueve
          rama-seis
          rama-siete
          rama-tres
          rama-uno
          seccion-contacto
          remotes/origin/HEAD -&amp;gt; origin/master
          remotes/origin/contenido-home
          remotes/origin/master
          remotes/origin/production

&lt;span class="c"&gt;# Puede ser que me falte hacer el prune y borrar las ramas locales&lt;/span&gt;
&lt;span class="c"&gt;# que se han quedado sin rama remota.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch-and-clear 
        Eliminada la rama rama-dos &lt;span class="o"&gt;(&lt;/span&gt;era 211751a&lt;span class="o"&gt;)&lt;/span&gt;..
        Eliminada la rama rama-nueve &lt;span class="o"&gt;(&lt;/span&gt;era 211751a&lt;span class="o"&gt;)&lt;/span&gt;..
        Eliminada la rama rama-seis &lt;span class="o"&gt;(&lt;/span&gt;era 211751a&lt;span class="o"&gt;)&lt;/span&gt;..
        Eliminada la rama rama-siete &lt;span class="o"&gt;(&lt;/span&gt;era 211751a&lt;span class="o"&gt;)&lt;/span&gt;..
        Eliminada la rama rama-tres &lt;span class="o"&gt;(&lt;/span&gt;era 211751a&lt;span class="o"&gt;)&lt;/span&gt;..
        Eliminada la rama rama-uno &lt;span class="o"&gt;(&lt;/span&gt;era 211751a&lt;span class="o"&gt;)&lt;/span&gt;..
        Eliminada la rama seccion-contacto &lt;span class="o"&gt;(&lt;/span&gt;era 2656b99&lt;span class="o"&gt;)&lt;/span&gt;..

&lt;span class="c"&gt;# Reviso por última vez y veo que está más limpio.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt;
          contenido-home
        &lt;span class="k"&gt;*&lt;/span&gt; master
          remotes/origin/HEAD -&amp;gt; origin/master
          remotes/origin/contenido-home
          remotes/origin/master
          remotes/origin/production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Modificar un tag
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;He creado un tag en el commit que no era; me he equivocado en el nombre del tag; he creado un tag del tipo que no era; etc&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Si no se ha subido todavía al repositorio remoto, basta con borrarlo y volver a crearlo.&lt;/p&gt;

&lt;blockquote&gt;


&lt;p&gt;🚨 &lt;strong&gt;Si ya se ha subido al repositorio remoto... se podría reemplazar, pero eso tendría consecuencias para otros desarrolladores.&lt;/strong&gt;&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Los tags no están pensados para ser modificados&lt;/strong&gt;, así que si alguien modifica un tag en el repositorio remoto, ya sea haciendo &lt;code&gt;git push -f&lt;/code&gt; o borrándolo y recreándolo, el resto de desarrolladores seguirían teniendo en sus locales la versión original del tag, ya que &lt;code&gt;git fetch&lt;/code&gt; no modifica tags.&lt;/p&gt;

&lt;p&gt;Y puede ser un problema si en algún momento hay que revertir alguna rama a ese tag o hay que sacar un fix para esa versión, ya que dependiendo de quien haga la operación los resultados serían distintos.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://git-scm.com/docs/git-tag#_on_re_tagging" rel="noopener noreferrer"&gt;documentación de Git se analiza este caso&lt;/a&gt;, y vienen a proponer dos soluciones.&lt;/p&gt;

&lt;p&gt;La primera es crear un nuevo tag, añadiéndole por ejemplo un sufijo (si el tag original era &lt;code&gt;1.0.0&lt;/code&gt; llamar al nuevo &lt;code&gt;1.0.0-the-good-one&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;La segunda opción es modificar el tag en el repositorio remoto y escribir al resto de desarrolladores explicando lo ocurrido y describiendo los pasos que hay que seguir para obtener el tag correcto (borrar el tag en local con &lt;code&gt;git tag --delete TAG&lt;/code&gt;, hacer &lt;code&gt;git fetch&lt;/code&gt; para obtener la nueva versión, y verificar que tienen el tag correcto con &lt;code&gt;git rev-parse TAG&lt;/code&gt; o &lt;code&gt;git show TAG&lt;/code&gt;) &lt;/p&gt;

&lt;p&gt;Aquí un ejemplo práctico.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Moratadelo crea un nuevo tag y lo sube al repositorio remoto.&lt;/span&gt;
mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"Implementado algoritmo secreto"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;master 2da5ad7] Implementado algoritmo secreto
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        Enumerando objetos: 5, listo.
        Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Compresión delta usando hasta 12 hilos
        Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;2/2&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Escribiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 285 bytes | 285.00 KiB/s, listo.
        Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/remotes/origin/
           409db7e..2da5ad7  master -&amp;gt; master

mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git tag &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Implementado algoritmo secreto"&lt;/span&gt;

mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git push origin 1.0.0
        Enumerando objetos: 1, listo.
        Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;1/1&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Escribiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;1/1&lt;span class="o"&gt;)&lt;/span&gt;, 169 bytes | 169.00 KiB/s, listo.
        Total 1 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/remotes/origin/
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new tag]         1.0.0 -&amp;gt; 1.0.0

&lt;span class="c"&gt;# Se lo comenta a Filemón, que hace git fectch para traerse todas&lt;/span&gt;
&lt;span class="c"&gt;# las novedades&lt;/span&gt;
filemon@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch
        remote: Enumerando objetos: 6, listo.
        remote: Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;6/6&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Total 4 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        Desempaquetando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;4/4&lt;span class="o"&gt;)&lt;/span&gt;, 402 bytes | 402.00 KiB/s, listo.
        Desde ~/sandbox/remotes/origin
           409db7e..2da5ad7  master     -&amp;gt; origin/master
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;nuevo tag]       1.0.0      -&amp;gt; 1.0.0

&lt;span class="c"&gt;# Por algúna razón Mortadelo se da cuenta de que hay un error &lt;/span&gt;
&lt;span class="c"&gt;# en código y decide actualizarlo.&lt;/span&gt;
mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="se"&gt;\&lt;/span&gt;
                   &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"Implementación sin errores del algoritmo secreto"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;master e985b90] Implementación sin errores del algoritmo secreto
         1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git push 
        Enumerando objetos: 5, listo.
        Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;5/5&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Compresión delta usando hasta 12 hilos
        Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;2/2&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Escribiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, 311 bytes | 311.00 KiB/s, listo.
        Total 3 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/remotes/origin/
           2da5ad7..e985b90  master -&amp;gt; master

&lt;span class="c"&gt;# Mortadelo no quiere que el primer tag del proyecto tenga &lt;/span&gt;
&lt;span class="c"&gt;# ese bug, así que intenta recrearlo, pero Git le da error.&lt;/span&gt;
mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git tag &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Implementado algoritmo secreto"&lt;/span&gt;
        fatal: el tag &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt; ya existe
&lt;span class="c"&gt;# Decidido a cubrir sus huellas opta por borrar el tag &lt;/span&gt;
&lt;span class="c"&gt;# y crear el bueno.&lt;/span&gt;
mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git tag &lt;span class="nt"&gt;--delete&lt;/span&gt; 1.0.0
        Etiqueta &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt; eliminada &lt;span class="o"&gt;(&lt;/span&gt;era b017cde&lt;span class="o"&gt;)&lt;/span&gt;

mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git tag &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Implementado algoritmo secreto"&lt;/span&gt;

&lt;span class="c"&gt;# Intenta pushearlo, pero el repositorio remoto lo rechaza&lt;/span&gt;
mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git push origin 1.0.0
        To ~/sandbox/remotes/origin/
         &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;rejected]        1.0.0 -&amp;gt; 1.0.0 &lt;span class="o"&gt;(&lt;/span&gt;already exists&lt;span class="o"&gt;)&lt;/span&gt;
        error: falló el push de algunas referencias a &lt;span class="s1"&gt;'~/sandbox/remotes/origin/'&lt;/span&gt;
        ayuda: Actualizaciones fueron rechazadas porque el tag ya existe en el remoto.

&lt;span class="c"&gt;# Resuelto quema todas las naves con un git push -f&lt;/span&gt;
mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;--force&lt;/span&gt; origin 1.0.0
        Enumerando objetos: 1, listo.
        Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;1/1&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        Escribiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;1/1&lt;span class="o"&gt;)&lt;/span&gt;, 171 bytes | 171.00 KiB/s, listo.
        Total 1 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        To ~/sandbox/remotes/origin/
         + b017cde...7a1b39e 1.0.0 -&amp;gt; 1.0.0 &lt;span class="o"&gt;(&lt;/span&gt;forced update&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Revisa la información del tag para comprobar que es la esperada.&lt;/span&gt;
mortadelo@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git show 1.0.0
        tag 1.0.0
        Tagger: mortadelo &amp;lt;mortadelo@tia.es&amp;gt;
        Date:   Sun Sep 19 17:19:08 2021 +0200

        Implementado algoritmo secreto

        commit e985b904626ff98b77b2478d15abd929d4b6237d &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master, tag: 1.0.0, origin/master, origin/HEAD&lt;span class="o"&gt;)&lt;/span&gt;
        Author: mortadelo &amp;lt;mortadelo@tia.es&amp;gt;
        Date:   Sun Sep 19 17:18:34 2021 +0200

            Implementación sin errores del algoritmo secreto


&lt;span class="c"&gt;# Filemón, hace git fetch, pero el tag no se actualiza.&lt;/span&gt;
filemon@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch
        remote: Enumerando objetos: 6, listo.
        remote: Contando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;6/6&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Comprimiendo objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;3/3&lt;span class="o"&gt;)&lt;/span&gt;, listo.
        remote: Total 4 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reusado 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;
        Desempaquetando objetos: 100% &lt;span class="o"&gt;(&lt;/span&gt;4/4&lt;span class="o"&gt;)&lt;/span&gt;, 430 bytes | 430.00 KiB/s, listo.
        Desde ~/sandbox/remotes/origin
           2da5ad7..e985b90  master     -&amp;gt; origin/master

&lt;span class="c"&gt;# Revisa su tag en local y es distinto al de Mortadelo, &lt;/span&gt;
&lt;span class="c"&gt;# ya que apunta a la versión con el bug.&lt;/span&gt;
filmemon@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git show 1.0.0
        tag 1.0.0
        Tagger: mortadelo &amp;lt;mortadelo@tia.es&amp;gt;
        Date:   Sun Sep 19 17:14:32 2021 +0200

        Implementado algoritmo secreto

        commit 2da5ad761654cd67bbd8bdfe1a9ac9891f04970f &lt;span class="o"&gt;(&lt;/span&gt;tag: 1.0.0&lt;span class="o"&gt;)&lt;/span&gt;
        Author: mortadelo &amp;lt;mortadelo@tia.es&amp;gt;
        Date:   Sun Sep 19 17:11:17 2021 +0200

            Implementado algoritmo secreto

&lt;span class="c"&gt;# Para tener el mismo tag que Mortadelo tendría que &lt;/span&gt;
&lt;span class="c"&gt;# borrar el tag en local.&lt;/span&gt;
filmemon@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git tag &lt;span class="nt"&gt;--delete&lt;/span&gt; 1.0.0
        Etiqueta &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt; eliminada &lt;span class="o"&gt;(&lt;/span&gt;era b017cde&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# Y hacer git fetch para obtener el nuevo tag&lt;/span&gt;
filmemon@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch
        Desde /home/claudio/sandbox/remotes/origin
         &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;nuevo tag]       1.0.0      -&amp;gt; 1.0.0

&lt;span class="c"&gt;# Revisa la información y ya ve lo mismo que Mortadelo.&lt;/span&gt;
filmemon@tia&lt;span class="nv"&gt;$ &lt;/span&gt;git show 1.0.0
        tag 1.0.0
        Tagger: mortadelo &amp;lt;mortadelo@tia.es&amp;gt;
        Date:   Sun Sep 19 17:19:08 2021 +0200

        Implementado algoritmo secreto

        commit e985b904626ff98b77b2478d15abd929d4b6237d &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master, tag: 1.0.0, origin/master, origin/HEAD&lt;span class="o"&gt;)&lt;/span&gt;
        Author: mortadelo &amp;lt;mortadelo@tia.es&amp;gt;
        Date:   Sun Sep 19 17:18:34 2021 +0200

            Implementación sin errores del algoritmo secreto

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Si has llegado hasta aquí, gracias 🙂&lt;br&gt;
Este era el último post de la serie; espero que este post, así como los anteriores, te hayan resultado útiles 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  Créditos
&lt;/h2&gt;

&lt;p&gt;Cover: &lt;a href="https://www.pexels.com/photo/photography-of-forest-during-daytime-1068508/" rel="noopener noreferrer"&gt;https://www.pexels.com/photo/photography-of-forest-during-daytime-1068508/&lt;/a&gt;&lt;br&gt;
Generación de diagramas: &lt;a href="https://excalidraw.com/" rel="noopener noreferrer"&gt;https://excalidraw.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>howto</category>
      <category>introduccion</category>
      <category>repositorioremoto</category>
    </item>
    <item>
      <title>Git: how to salir de esta, ramas</title>
      <dc:creator>Claudio Sánchez</dc:creator>
      <pubDate>Mon, 19 Jul 2021 15:23:47 +0000</pubDate>
      <link>https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74</link>
      <guid>https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74</guid>
      <description>&lt;h2&gt;
  
  
  How to
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introducción&lt;/li&gt;
&lt;li&gt;Orientarse dentro de una rama&lt;/li&gt;
&lt;li&gt;Renombrar una rama&lt;/li&gt;
&lt;li&gt;Recuperar una rama borrada por error&lt;/li&gt;
&lt;li&gt;Git merge, ese comando problemático&lt;/li&gt;
&lt;li&gt;Mover commits&lt;/li&gt;
&lt;li&gt;Mover ramas&lt;/li&gt;
&lt;li&gt;Deshacer un merge&lt;/li&gt;
&lt;li&gt;¿Cómo integrar una rama?&lt;/li&gt;
&lt;li&gt;HEAD detached o desacoplado&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;Con un GUI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OciAjQVR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dmg19wglikjeo4gmbzuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OciAjQVR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dmg19wglikjeo4gmbzuh.png" alt="Ramas vistas en un GUI" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O por consola.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'%C(auto)%h %s%n%C(auto)%d%n'&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8XdU1-mm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q294qcmw6oi2l4dk8r4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8XdU1-mm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q294qcmw6oi2l4dk8r4z.png" alt="Ramas vistas en consola" width="612" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una forma de visualizar los commits de un repositorio es en un árbol, donde los commits son los nudos de las ramas. &lt;/p&gt;

&lt;p&gt;De un commit  pueden salir uno o varios commits (por ejemplo, de &lt;em&gt;"todos: concilio del anillo"&lt;/em&gt; sólo sale el commit &lt;em&gt;"todos: moria"&lt;/em&gt;, mientras que de &lt;em&gt;"todos - gandalf: amon hen"&lt;/em&gt; salen tres, &lt;em&gt;"aragorn + legolas + gimli: siguiendo a los uruk-hai..."&lt;/em&gt;, &lt;em&gt;"pipin + merry: camino a isengard"&lt;/em&gt;  y &lt;em&gt;"frodo + sam: camino a mordor"), y&lt;/em&gt; los commits se pueden unir de dos en dos (por ej. &lt;em&gt;"aragorn + legolas + gimli + gandalf: fangorn"&lt;/em&gt; es la unión de los commits &lt;em&gt;"aragorn + legolas + gimli: siguiendo a los uruk-ahi" y "gandalf: cayendo con el balrog").&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cuando el commit es la unión de dos commits se llama &lt;em&gt;"merge commit"&lt;/em&gt;, ya que es el resultado de  &lt;code&gt;git merge&lt;/code&gt;  o &lt;code&gt;git pull&lt;/code&gt; (sí, porque &lt;code&gt;git pull&lt;/code&gt; hace merges por debajo), mientras que el resto de los commits suelen ser resultado de &lt;code&gt;git commit&lt;/code&gt;, aunque también serlo de &lt;code&gt;git revert&lt;/code&gt; o de &lt;code&gt;git merge --squash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Las ramas son referencias a commits, referencias que cambian al realizar acciones como &lt;code&gt;git commit&lt;/code&gt; o  &lt;code&gt;git merge&lt;/code&gt; estando en esa rama (por ej. la rama &lt;em&gt;"pippin-merry"&lt;/em&gt; estaba en el commit &lt;em&gt;"pippin + merry: camino a insengard"&lt;/em&gt;, y se modifico automáticamente para referenciar a &lt;em&gt;"pippin-merry: concilio de los ents"&lt;/em&gt; cuando se hizo dicho commit). &lt;/p&gt;

&lt;p&gt;Múltiples ramas pueden hacer referencia al mismo commit (por ej. las ramas &lt;em&gt;"gandalf"&lt;/em&gt; y  &lt;em&gt;"aragorn-legolar-gimli"&lt;/em&gt; hacen referencia al commit &lt;code&gt;872cac9&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Este post va a lidiar &lt;strong&gt;solo con casos que pueden surgir al trabajar con ramas locales&lt;/strong&gt;, es decir, aquellas ramas creadas localmente y que todavía no se han subido a un repositorio remoto. &lt;br&gt;
Para manipular ramas en repositorio remoto con &lt;code&gt;git pull&lt;/code&gt; o sincronizar las ramas locales con las ramas del repositorio remoto  &lt;code&gt;git push&lt;/code&gt;, hay que tener en cuenta una serie de cosas que se tratarán en el siguiente post.&lt;/p&gt;
&lt;h2&gt;
  
  
  Orientarse dentro de una rama
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;¿Cómo obtengo el commit anterior?; ¿Cuál era el commit antes del merge?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HEAD&lt;/code&gt; siempre indica el commit actual y &lt;code&gt;HEAD~&lt;/code&gt; siempre indica el commit anterior.&lt;br&gt;
Refiendose a ramas, &lt;code&gt;master&lt;/code&gt; indica el último commit de la &lt;code&gt;master&lt;/code&gt; y &lt;code&gt;master~&lt;/code&gt; indica el commit anterior.&lt;br&gt;
Y refiriendose a commits, &lt;code&gt;872cac9&lt;/code&gt; indica el commit &lt;code&gt;872cac9&lt;/code&gt; y &lt;code&gt;872cac9~&lt;/code&gt; indica el commit anterior.&lt;br&gt;
Estas referencias facilitan las operaciones más o menos cotidianas como pueden ser el deshacer el commit actual; &lt;code&gt;git reset HEAD~&lt;/code&gt; es mucho más rápido que &lt;code&gt;git log&lt;/code&gt; para obtener el hash del commit anterior y luego hacer &lt;code&gt;git reset &amp;lt;hash&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ya a modo de curiosidad, &lt;code&gt;~&lt;/code&gt; es una &lt;em&gt;"referencia por ancestro"&lt;/em&gt; que indica el commit padre. Se pueden añadir todos los &lt;code&gt;~&lt;/code&gt; que se quieran para obtener referencias a commits anteriores; &lt;code&gt;HEAD~&lt;/code&gt; referencia al commit &lt;em&gt;"padre"&lt;/em&gt;; &lt;code&gt;HEAD~~&lt;/code&gt;, o &lt;code&gt;HEAD~2&lt;/code&gt; referencian al commit &lt;em&gt;"abuelo"&lt;/em&gt;; &lt;code&gt;HEAD~3&lt;/code&gt; referencian al &lt;em&gt;"bisabuelo"&lt;/em&gt;; etc.&lt;/p&gt;

&lt;p&gt;También existen &lt;code&gt;^1&lt;/code&gt;, o simplemente &lt;code&gt;^&lt;/code&gt;, y &lt;code&gt;^2&lt;/code&gt;, para hacer referencias a los commits implicados en  &lt;em&gt;merge commits&lt;/em&gt; ; si &lt;code&gt;HEAD&lt;/code&gt; es un merge commit, &lt;code&gt;HEAD^&lt;/code&gt; es equivalente a &lt;code&gt;HEAD~&lt;/code&gt;, e indica el commit en el que se estaba cuando se hizo &lt;code&gt;git merge&lt;/code&gt;; &lt;code&gt;HEAD^2&lt;/code&gt; indica el último commit de la rama con la que se hizo merge.&lt;br&gt;
Y se pueden combinar para hacer cosas como &lt;code&gt;HEAD^2~2&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Renombrar una rama
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Corregir un texto incorrecto; se copio la clave del issute tracker que no era.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;En un GUI se puede hacer click derecho en el nombre de la rama y click en &lt;em&gt;"Rename".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Si es por consola hay que usar &lt;code&gt;git branch -m&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# git status para ver la rana actual.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    En la rama fature
    nada para hacer commit, el árbol de trabajo está 
        limpio

&lt;span class="c"&gt;# O git status para ver todas las ramas, &lt;/span&gt;
&lt;span class="c"&gt;# con un * delante de la rama actual.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch
      dovolop
    &lt;span class="k"&gt;*&lt;/span&gt; fature
      master

&lt;span class="c"&gt;# Renombrar la rama actual.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-m&lt;/span&gt; feature

&lt;span class="c"&gt;# Renombrar otra rama.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-m&lt;/span&gt; dovolop develop

&lt;span class="nv"&gt;$ &lt;/span&gt;git branch
      develop
    &lt;span class="k"&gt;*&lt;/span&gt; feature
      master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estas acciones solo renombran la rama local y no afectan al nombre de la rama en el repositorio remoto; si hay que renombrar una rama en el repositorio hay que tener en cuenta más detalles que se explicará en el post de repositorios remotos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recuperar una rama borrada por error
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Me equivoque al poner el nombre de la rama cuando ejecute el comando; pensaba que sólo era pruebas, pero no...; la he borrado antes de subirla al repositorio remoto; pensaba que ya había subido todo al repositorio remoto, pero faltaba un commit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para borrar una rama en un GUI, click derecho en el nombre de la rama y &lt;em&gt;"Delete"&lt;/em&gt;. &lt;br&gt;
Algunos GUI, tras borrar una rama, dan la opción de recuperarla.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KP77xv-g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2u6xew90iydbx6xnl25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KP77xv-g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2u6xew90iydbx6xnl25.png" alt="GUI restaura rama" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si el mensaje es &lt;em&gt;"Unmerged commits were discarted"&lt;/em&gt;,  es recomendable prestarle atención, porque puede ser uno de los casos en los que interese recuperar la rama.&lt;/p&gt;

&lt;p&gt;Se pueden borrar ramas de dos maneras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git branch --delete &amp;lt;rama&amp;gt;&lt;/code&gt; o &lt;code&gt;git branch -d &amp;lt;rama&amp;gt;&lt;/code&gt;:  Git comprobará si &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt; esta mergeada en la rama actual, y de no estarla, no permitirá borrar la rama, evitando así que puedan perderse commits.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git branch --delete --force &amp;lt;rama&amp;gt;&lt;/code&gt; o &lt;code&gt;git branch -D &amp;lt;rama&amp;gt;&lt;/code&gt;:  borra la rama, este o no mergeada en la rama actual.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como norma general es preferible usar &lt;code&gt;git branch -d&lt;/code&gt; para ir sobre seguro, y &lt;code&gt;git branch -D&lt;/code&gt; solo para esos casos en los que se esta completamente seguro.&lt;/p&gt;

&lt;p&gt;Ya en el tema del HOW TO, es posible recrear la rama con  &lt;code&gt;git branch &amp;lt;rama&amp;gt; &amp;lt;hash&amp;gt;&lt;/code&gt;, donde &lt;code&gt;&amp;lt;hash&amp;gt;&lt;/code&gt; indicaría el último commit de la rama en el momento de borrarla. &lt;br&gt;
Si no se conoce ese hash y la rama se borro hace poco, &lt;code&gt;git reflog&lt;/code&gt; puede ser una buena opción para buscarlo, ya que muestra un histórico de todos los commits por los que se ha pasado. En &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#deshacer-git-reset"&gt;Deshacer un git reset&lt;/a&gt; hay más detalles sobre &lt;code&gt;git reflog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si la rama se borro hace  mucho tiempo, &lt;code&gt;git reflog&lt;/code&gt; puede no ser la mejor opción, ya que el hash que se busca puede estar enterrado entre muchos otros. Documentándome para el post he visto opciones mejores como &lt;a href="https://stackoverflow.com/a/22303923/1587302"&gt;esta&lt;/a&gt; o &lt;a href="https://gist.github.com/jbgo/1944238"&gt;esta&lt;/a&gt;, pero personalmente no me ha surgido el caso de tener que recuperar una rama borrada hace semanas.&lt;/p&gt;

&lt;p&gt;¿Y si la rama se ha borrado en un repositorio remoto? Tras recrear la rama en local habría que subirla al repositorio.&lt;/p&gt;

&lt;p&gt;Haciendo un ejemplo práctico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-vv&lt;/span&gt;
      feature/create-home   6748ee2 crear hoja de estilos                             home.css
      feature/setup-project 9e75aa0 añadido .gitignore
    &lt;span class="k"&gt;*&lt;/span&gt; master                9e75aa0 añadido .gitignore

&lt;span class="c"&gt;# Como la rama feature/setup-project está mergeada en master&lt;/span&gt;
&lt;span class="c"&gt;# se borra sin problemas.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-d&lt;/span&gt; feature/setup-project 
    Eliminada la rama feature/setup-project &lt;span class="o"&gt;(&lt;/span&gt;era 9e75aa0&lt;span class="o"&gt;)&lt;/span&gt;..

&lt;span class="c"&gt;# Como la rama feature/create-home no está mergeada en master&lt;/span&gt;
&lt;span class="c"&gt;# borrarla con -d da error.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-d&lt;/span&gt; feature/create-home 
    error: La rama &lt;span class="s1"&gt;'feature/create-home'&lt;/span&gt; no ha sido fusionada completamente.
    Si estás seguro de querer borrarla, ejecuta &lt;span class="s1"&gt;'git branch -D feature/create-home'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Si se fuerza el borrado si que deja.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-D&lt;/span&gt; feature/create-home 
    Eliminada la rama feature/create-home &lt;span class="o"&gt;(&lt;/span&gt;era 6748ee2&lt;span class="o"&gt;)&lt;/span&gt;..

&lt;span class="c"&gt;# Pero me doy cuenta de mi error :(&lt;/span&gt;

&lt;span class="c"&gt;# Así que busco el commit.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reflog 
    ...
    9e75aa0 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;6&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from feature/create-home to master


&lt;span class="c"&gt;# Y recreo la rama.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch feature/create-home 6748ee2

&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-vv&lt;/span&gt;
      feature/create-home 6748ee2 crear hoja de estilos home.css
    &lt;span class="k"&gt;*&lt;/span&gt; master              9e75aa0 añadido .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Git merge, ese comando problemático
&lt;/h2&gt;

&lt;p&gt;"&lt;em&gt;git merge" cada vez hace una cosa distinta; después de hacer "git merge" la aplicación ya no funciona.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git merge&lt;/code&gt; puede hacer cosas distintas dependiendo de las diferencias que haya entre la rama actual y la rama que se quiere mergear.&lt;/p&gt;

&lt;p&gt;El siguiente diagrama de flujo resume la lógica que hay por debajo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2jE6zwOY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/369txvabk90k0698k5xd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2jE6zwOY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/369txvabk90k0698k5xd.png" alt="diagrama flujo de git merge" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es &lt;em&gt;"fast forward"&lt;/em&gt;  cuando  la rama que se quiere mergear, &lt;code&gt;target&lt;/code&gt;,  ha partido del último commit de la rama actual; en este caso &lt;code&gt;git merge&lt;/code&gt; simplemente modificará la referencia de la rama actual para que apunte al mismo commit que la rama &lt;code&gt;target&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por poner un ejemplo, supongamos que se quiere mergear la rama &lt;code&gt;feature/create-home&lt;/code&gt; en la rama &lt;code&gt;master&lt;/code&gt;;  dado que &lt;code&gt;feature/create-home&lt;/code&gt; parte de &lt;code&gt;master&lt;/code&gt; &lt;code&gt;git merge&lt;/code&gt; por defecto hará &lt;em&gt;fast forward&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SBCT045k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64ypccsf4nig57mbxlp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SBCT045k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64ypccsf4nig57mbxlp8.png" alt="git merge fast forward antes" width="381" height="203"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    En la rama master

&lt;span class="nv"&gt;$ &lt;/span&gt;git merge feature/create-home
    Actualizando 85b13b4..82975ee
    Fast-forward
     home.css  | 3 +++
     home.html | 2 ++
     2 files changed, 5 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 home.css
     create mode 100644 home.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HIdwTMzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8dri52hslhogll5xccf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HIdwTMzO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8dri52hslhogll5xccf.png" alt="git merge fast forward despues" width="395" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si no es &lt;em&gt;fast forward&lt;/em&gt; , y no hay conflictos, &lt;code&gt;git merge&lt;/code&gt; creará un &lt;em&gt;merge commit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5f47uQwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v4q3hvxt1zo8t0x8f6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5f47uQwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v4q3hvxt1zo8t0x8f6m.png" alt="git merge merge commit antes" width="412" height="249"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    En la rama master

&lt;span class="nv"&gt;$ &lt;/span&gt;git merge feature/create-home
   &lt;span class="c"&gt;# Se abre un editor de texto para poder personalizar el &lt;/span&gt;
   &lt;span class="c"&gt;# mensaje del commit.&lt;/span&gt;
   &lt;span class="c"&gt;# Tras guardar el mensaje:&lt;/span&gt;
    Merge made by the &lt;span class="s1"&gt;'recursive'&lt;/span&gt; strategy.
     home.css  | 3 +++
     home.html | 2 ++
     2 files changed, 5 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 home.css
     create mode 100644 home.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bVS1epwX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfik953fkzcvdcrklow8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bVS1epwX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfik953fkzcvdcrklow8.png" alt="git merge merge commit después" width="433" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si no es &lt;em&gt;fast forward&lt;/em&gt; , y  hay conflictos... bien, es un momento que a nadie le gusta.&lt;br&gt;
Los conflictos surgen cuando en las dos ramas se han tocado los mismos trozos de código, ya sea editándolos en ambas ramas, modificando el archivo en una y renombrándolo en la otra, etc.&lt;br&gt;
Cuando surjan, Git modificará los archivos con conflictos para indicar dónde están y esperará a que se resuelvan, pero no hará nada más.  Será el momento de analizar que ha pasado y resolver los conflictos. &lt;br&gt;
Y siempre se puede  ejecutar &lt;code&gt;git reset --hard&lt;/code&gt; para hacer tabla rasa y empezar de cero, porque hay veces en que los conflictos se resuelven y los tests dejan de pasar, o simplemente porque los conflictos son complicados y se prefiere empezar fresco después de una pausa.&lt;/p&gt;

&lt;p&gt;Los conflictos se verán así en el archivo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;lt; HEAD
&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"contact.html"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;Contacto&amp;lt;/a&amp;gt;
&lt;span class="o"&gt;=======&lt;/span&gt;
&amp;lt;h1&amp;gt; Home &amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt; bienvenido &amp;lt;/p&amp;gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; feature/create-home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Donde entre &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; y &lt;code&gt;=======&lt;/code&gt; esta lo que hay en la rama actual, y entre &lt;code&gt;========&lt;/code&gt; y  &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; lo que hay en la rama a mergear.&lt;/p&gt;

&lt;p&gt;Para estos casos lo más cómodo es recurrir a un GUI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nGPcM6fH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xv9nfaobwqhe7abhj67c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nGPcM6fH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xv9nfaobwqhe7abhj67c.png" alt="git merge resolver conflictos antes" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez resuelto&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D2hsMgKO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4g0fetee0848ovb5mqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D2hsMgKO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4g0fetee0848ovb5mqe.png" alt="git merge resolver conflictos despues" width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya se podrá hacer commit:.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git merge feature/create-home 
    CONFLICTO &lt;span class="o"&gt;(&lt;/span&gt;add/add&lt;span class="o"&gt;)&lt;/span&gt;: Conflicto de merge en home.html
    Auto-fusionando home.html
    Fusión automática falló&lt;span class="p"&gt;;&lt;/span&gt; arregle los conflictos y luego realice 
        un commit con el resultado.

&lt;span class="c"&gt;# Resolver conflictos.&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-a&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;master 1814deb] Merge branch &lt;span class="s1"&gt;'feature/create-home'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xQvkVYBF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9wwfahfr0su75dg96bw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xQvkVYBF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9wwfahfr0su75dg96bw.png" alt="git merge merge commit tras conflictos" width="465" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando haya un &lt;em&gt;merge commit&lt;/em&gt; de por medio siempre hay que tener cuidado, ya que si bien puede no haber conflictos si que se pueden haber introducir errores. &lt;br&gt;
Si por ejemplo en la rama actual se renombrase la función &lt;code&gt;doThings&lt;/code&gt; a &lt;code&gt;createUser&lt;/code&gt;, junto con todos sus usos, y se mergease una rama que ha introducido un nuevo uso de &lt;code&gt;doThings&lt;/code&gt; en un nuevo archivo, &lt;code&gt;git merge&lt;/code&gt;  puede no encontrar conflictos y mergear automáticamente,  pero cuando se invoque &lt;code&gt;doThings&lt;/code&gt; en el nuevo archivo se producirá un error, ya que &lt;code&gt;doThings&lt;/code&gt; ha dejado de existir. &lt;br&gt;
Para evitar estos problemas se pueden usar varias estrategias:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ejecutar los tests después de cada merge, y si hay algún problema hacer commits con los fixes.&lt;/li&gt;
&lt;li&gt;Crear un &lt;em&gt;&lt;a href="https://git-scm.com/docs/githooks"&gt;hook&lt;/a&gt;&lt;/em&gt; que impida  completar el merge si fallan los tests.&lt;/li&gt;
&lt;li&gt;Usar algunas de las opciones de &lt;code&gt;git merge&lt;/code&gt; para controlar como se hace el merge:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--ff-only&lt;/code&gt;  para indicar que solo se quiere hacer merge si es  &lt;em&gt;fast forward&lt;/em&gt;, fallando en caso contrario ( por ej. &lt;code&gt;git merge --ff-only feature/create-home&lt;/code&gt;).
Puede ser útil para actualizar ramas importantes como &lt;code&gt;master&lt;/code&gt; con total tranquilidad.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--no-commit&lt;/code&gt; fuerza a que si el merge implica un &lt;em&gt;merge commit&lt;/em&gt;, Git se detenga justo antes de hacer el commit, como haría si hubiese conflictos; en ese momento se podrán revisar los cambios, ejecutar los tests, arreglar alguna cosilla su fuese necesario, y finalmente, hacer el commit. 
Si el merge es  &lt;em&gt;fast forward&lt;/em&gt; este se hará automáticamente usando la estrategia de &lt;em&gt;fast forward&lt;/em&gt;, ignorando el flag &lt;code&gt;--no-commit&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Mover commits
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;He hecho un commit en la rama que no era; se me olvido crear la rama antes de hacer los commits.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lo primero sería llevarse los commits a la rama adecuada.&lt;br&gt;
Si la rama en la que se deberían haber hecho los commits no existe, es tan sencilla como crearla en el punto actual: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si se usa un GUI, click derecho en la rama actual y crear una nueva rama.&lt;/li&gt;
&lt;li&gt;Si se usa consola &lt;code&gt;git branch &amp;lt;rama&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si la rama ya estaba creada, basta con ir al ella y hacer &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#como-compartir"&gt;&lt;code&gt;git cherry-pick&lt;/code&gt;&lt;/a&gt; de los commits que se quieren mover.&lt;/p&gt;

&lt;p&gt;Y los segundo y último es &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#borron-cuenta-nueva"&gt;restaurar la rama&lt;/a&gt; en la que se han hecho los commits por error al punto correcto .&lt;/p&gt;

&lt;p&gt;Al final muchas situaciones en Git se resuelven combinando varias acciones. &lt;/p&gt;
&lt;h2&gt;
  
  
  Mover ramas
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Saque la rama del hotfix de mi rama de feature en lugar de sacarla de master; saque mi rama de feature de master en lugar de la rama de integración.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Un ejemplo de esta situación sería sacar la rama &lt;code&gt;hotfix&lt;/code&gt; de la rama de integración &lt;code&gt;develop&lt;/code&gt;, en lugar de haberlo hecho de la rama principal &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si no se ha hecho ningún commit bastaría con modificar la rama &lt;code&gt;hotfix&lt;/code&gt; para que parta de &lt;code&gt;master&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si se usa un GUI, click derecho en &lt;code&gt;master&lt;/code&gt; y click en  &lt;em&gt;"Reset current branch to here"&lt;/em&gt; o similar.&lt;/li&gt;
&lt;li&gt;Si se usa consola &lt;code&gt;git checkout -B hotfix master&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si ya se ha hecho algún commit, la opción que menos comandos requiere es &lt;code&gt;git rebase&lt;/code&gt;, aunque hay que visualizar muy bien lo que se quiere hacer antes de usarlo.&lt;br&gt;
Otra opción algo más laboriosa sería:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apuntarse el hash de los commits que han hecho en la rama &lt;code&gt;hotfix&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Resetear la rama &lt;code&gt;hotfix&lt;/code&gt; para que apunte al punto correcto con &lt;em&gt;"Reset current branch to here"&lt;/em&gt; si se una GUI o &lt;code&gt;git checkout -B hotfix master&lt;/code&gt; si se usa consola.&lt;/li&gt;
&lt;li&gt;Recuperar los commits con apuntados en el paso 1 con &lt;code&gt;git cherry-pick&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La forma por defecto de &lt;code&gt;git rebase&lt;/code&gt; es &lt;code&gt;git rebase &amp;lt;rama-destino&amp;gt; &amp;lt;rama-a-mover&amp;gt;&lt;/code&gt;, o, si ya se está en &lt;code&gt;&amp;lt;rama-a-mover&amp;gt;&lt;/code&gt;, simplemente &lt;code&gt;git rebase &amp;lt;rama-destino&amp;gt;&lt;/code&gt;; haciendo un símil, sería como "trasplantar la rama".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JHVn6GrL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m2cjtaqaprhorwljmfrj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JHVn6GrL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m2cjtaqaprhorwljmfrj.png" alt="git rebase sencillo" width="709" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el ejemplo, &lt;code&gt;git rebase master hotfix&lt;/code&gt;  movería los commits de la rama &lt;code&gt;hotfix&lt;/code&gt; para que salgan del commit &lt;code&gt;G&lt;/code&gt; en lugar del commit &lt;code&gt;E&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;(Como nota aclaratoria, añado un apostrofe para indicar que el commit con hash &lt;code&gt;A'&lt;/code&gt;  es una copia &lt;code&gt;A&lt;/code&gt; pero con distinto padre; decir "mover" no es del todo correcto, pero es una &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#introduccion"&gt;simplificación  bastante útil&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Por defecto &lt;code&gt;git rebase&lt;/code&gt;  mueve  todos los commits de  &lt;code&gt;&amp;lt;rama-a-mover&amp;gt;&lt;/code&gt; que no tiene &lt;code&gt;&amp;lt;rama-destino&amp;gt;&lt;/code&gt;, incluso aunque alguno de esos commits estén compartidos con otra rama.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wji3DSK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v36dcjpqa82kebqr2tba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wji3DSK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v36dcjpqa82kebqr2tba.png" alt="git rebase complejo" width="714" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el ejemplo, &lt;code&gt;git rebase master hotfix&lt;/code&gt; movería los commits &lt;code&gt;E y F&lt;/code&gt;, que solo tiene  &lt;code&gt;hotfix&lt;/code&gt;, y copiaría los commits &lt;code&gt;C, D y F&lt;/code&gt;, que &lt;code&gt;hotfix&lt;/code&gt; comparte con la rama  &lt;code&gt;develop&lt;/code&gt; y que no están en en &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si el algún momento se llegasen a mergear las ramas &lt;code&gt;hotfix&lt;/code&gt; y &lt;code&gt;develop&lt;/code&gt; en &lt;code&gt;master&lt;/code&gt; no habría conflictos porque, aunque los commits &lt;code&gt;C', D' y F'&lt;/code&gt; estén duplicados en la rama  &lt;code&gt;develop&lt;/code&gt;, Git detectaría que son lo mismo.&lt;/p&gt;

&lt;p&gt;Se puede indicar de una manera más precisa los commits que hay que mover con el comando&lt;br&gt;
&lt;code&gt;git rebase --onto &amp;lt;rama-destino&amp;gt; &amp;lt;desde-la-rama&amp;gt; &amp;lt;rama-a-mover&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wji3DSK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v36dcjpqa82kebqr2tba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wji3DSK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v36dcjpqa82kebqr2tba.png" alt="git rebase onto" width="714" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el ejemplo &lt;code&gt;git rebase --onto master develop hotfix&lt;/code&gt;  movería solo los commits  &lt;code&gt;E y F&lt;/code&gt;, que están en la rama  &lt;code&gt;hotfix&lt;/code&gt; y salen de la rama &lt;code&gt;develop&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Como se decía al principio, &lt;code&gt;git rebase&lt;/code&gt; es lo que menos comandos requiere, pero en contra tiene que lleva su tiempo visualizarlo.&lt;/p&gt;

&lt;p&gt;Otra nota sobre &lt;code&gt;git rebase&lt;/code&gt; es que puede implicar resolver conflictos varias veces si las ramas de origen y destino son muy distintas; si eso ocurre, siempre se puede dar marchar atrás con  &lt;code&gt;git rebase --abort&lt;/code&gt; y replantarse la estrategia.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deshacer un merge
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Un merge que produce un error; un merge hecho donde en una rama que no era; un merge hecho con la rama que no era.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Si se acaba de hacer el merge y no se ha subido a un repositorio remoto lo más sencillo es &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#borron-cuenta-nueva"&gt;revertir la rama al commit&lt;/a&gt; en el que estaba antes del merge.&lt;/p&gt;

&lt;p&gt;Si se han hecho commits después del merge o ya se han subido al repositorio remoto, se pueden deshacer con &lt;code&gt;git revert&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si el merge fue &lt;em&gt;fast forward&lt;/em&gt;, habría que hacer un &lt;code&gt;git revert&lt;/code&gt; de cada uno de los commits que se han añadido con el merge, empezando por el más reciente.&lt;br&gt;
Más sobre como revertir commits simples en &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#revertir-commit"&gt;Deshacer un commit: como revertir un cambio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Si el merge implico un &lt;em&gt;merge commit&lt;/em&gt; se puede usar &lt;code&gt;git revert -m1 &amp;lt;hash&amp;gt;&lt;/code&gt;, donde &lt;code&gt;-m1&lt;/code&gt; indica que se desean deshacer los cambios que vinieron de &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt; cuando se hizo  &lt;code&gt;git merge &amp;lt;rama&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;También se puede usar, aunque es menos común, &lt;code&gt;git revert -m2 &amp;lt;hash&amp;gt;&lt;/code&gt; para indicar que se desean deshacer las diferencias que había en la rama en la que se hizo &lt;code&gt;git merge &amp;lt;rama&amp;gt;&lt;/code&gt; con  respecto de &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt;, para que tras el &lt;code&gt;git revert&lt;/code&gt; se tenga lo mismo que en &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Estos comando generarán un commit con los cambios para deshacer el &lt;em&gt;merge commit&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Con un ejemplo práctico.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Acabo de hacer un merge y lo quiero deshacer.&lt;/span&gt;

&lt;span class="c"&gt;# Hago git log -1 para ver la información del último commit.&lt;/span&gt;
&lt;span class="c"&gt;# 'Merge: 6512051 6748ee2' me dice que &lt;/span&gt;
&lt;span class="c"&gt;# estaba en el commit 6512051 cuando hice el merge &lt;/span&gt;
&lt;span class="c"&gt;# de otra rama que a su vez estaba en el commit 6748ee2.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt;
    commit 7a12efcf980753856b67b72b040a73a93cdb3c9b &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt;
    Merge: 6512051 6748ee2

        Merge branch &lt;span class="s1"&gt;'feature/create-home'&lt;/span&gt;

&lt;span class="c"&gt;# Compruebo cuales son las diferencias entre el commit&lt;/span&gt;
&lt;span class="c"&gt;# 6512051 y el commit en el que estoy.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git diff 6512051 HEAD 
    diff &lt;span class="nt"&gt;--git&lt;/span&gt; a/home.css b/home.css
    new file mode 100644
    index 0000000..6748ee2
    &lt;span class="nt"&gt;---&lt;/span&gt; /dev/null
    +++ b/home.css
    ...
    diff &lt;span class="nt"&gt;--git&lt;/span&gt; a/home.html b/home.html
    new file mode 100644
    index 0000000..6141d5d
    &lt;span class="nt"&gt;---&lt;/span&gt; /dev/null
    +++ b/home.html
    ...

&lt;span class="c"&gt;# Hago el revert del merge indicando con -m1 que quiero&lt;/span&gt;
&lt;span class="c"&gt;# tomar como referencia lo que había antes del merge.  &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git revert &lt;span class="nt"&gt;-m1&lt;/span&gt; 7a12efcf980753856b67b72b040a73a93cdb3c9b
    &lt;span class="o"&gt;[&lt;/span&gt;master f65033c] Revert &lt;span class="s2"&gt;"Merge branch 'feature/create-home'"&lt;/span&gt;
     1 file changed, 2 deletions&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# log -1 me indica que hay nuevo commit.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; f65033c
    commit f65033c1cb53ab664482d9d7ee3f836a493e249f

        Revert &lt;span class="s2"&gt;"Merge branch 'feature/create-home'"&lt;/span&gt;

        This reverts commit 7a12efcf980753856b67b72b040a73a93cdb3c9b, reversing
        changes made to 651205183ba4da49663163b881901c74e8c98606.

&lt;span class="c"&gt;# Compruebo los cambios y no hay diferencias.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git diff 6512051 HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Qué ocurriría si se mergease de nuevo la rama cuyo merge se ha revertido? &lt;br&gt;
Si no se ha hecho ningún commit adicional en &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt;, &lt;code&gt;git merge &amp;lt;rama&amp;gt;&lt;/code&gt;  dirá que "la rama ya está actualizada" y no hará nada, aunque quizá lo natural sería pensar que volvería a aplicar los cambios de &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt;.&lt;br&gt;
Si se ha hecho algún commit adicional en &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt;, &lt;code&gt;git merge &amp;lt;rama&amp;gt;&lt;/code&gt; solo aplicará los cambios de los nuevos commits; la "buena" noticia es que en &lt;code&gt;git merge&lt;/code&gt; notificará unos conflictos bastante extraños que harán ver que algo raro pasa.&lt;br&gt;
Todo eso resulta un poco contraintuitivo, pero  &lt;code&gt;git revert&lt;/code&gt; sólo modifica archivos, no modifica el histórico de commits, así que cuando se le pide a Git que mergee commits que ya tiene en su histórico, se limita a ignorarlos porque ya los tiene.&lt;/p&gt;

&lt;p&gt;¿Por qué alguien querría mergear de nuevo algo que acaba de revertir? &lt;br&gt;
Si un &lt;em&gt;merge commit&lt;/em&gt; causa problemas en producción, una forma rápida de salir del paso es revertir ese &lt;em&gt;merge commit&lt;/em&gt;, arreglar el problema en la rama y volver a mergearla.&lt;br&gt;&lt;br&gt;
Pero como se sigue de la pregunta anterior no es algo directo.&lt;br&gt;
En &lt;a href="https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt"&gt;https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt&lt;/a&gt; se explican muy bien dos posibles maneras para hacerlo.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resolver los problemas en la rama cuyo &lt;em&gt;merge commit&lt;/em&gt; se ha revertido, revertir el commit que revirtió el &lt;em&gt;merge commit&lt;/em&gt;  y por último mergear la rama con el fix. &lt;/li&gt;
&lt;li&gt;Replicar en una nueva rama todos los commits de la rama cuyo &lt;em&gt;merge commit&lt;/em&gt; se ha revertido (los commits tendrían los mismos cambios, pero como tendrían un hash distinto para Git serían distintos), resolver los problemas en la nueva rama y mergearla.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/OK27wINdQS5YQ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/OK27wINdQS5YQ/giphy.gif" alt="https://media.giphy.com/media/OK27wINdQS5YQ/giphy.gif" width="443" height="312"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Cómo integrar una rama?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;He terminado mi flamante primera feature, los tests están en verde, ha pasado las revisiones de código,  y ahora ¿como la integro?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Supongamos que se quiere integrar la rama &lt;code&gt;feature/create-home&lt;/code&gt; en la rama &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UTVjhjpA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vskkjj8whcu9sgyz94pd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UTVjhjpA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vskkjj8whcu9sgyz94pd.png" alt="escenario integrar rama" width="376" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algunas de las estrategias más habituales son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merge commit&lt;/li&gt;
&lt;li&gt;Merge squash&lt;/li&gt;
&lt;li&gt;Rebase&lt;/li&gt;
&lt;li&gt;Trunk base development&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Merge commit
&lt;/h3&gt;

&lt;p&gt;Crear un &lt;em&gt;merge commit&lt;/em&gt; cada vez que se mergee una rama en master: &lt;code&gt;git merge --no-ff &amp;lt;rama&amp;gt;&lt;/code&gt;. &lt;br&gt;
&lt;code&gt;--no-ff&lt;/code&gt; sirve para forzar que se cree un &lt;em&gt;merge commit&lt;/em&gt;, aunque se pudiese hacer &lt;em&gt;fast forward.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Me aseguro de que estoy en la rama master, &lt;/span&gt;
&lt;span class="c"&gt;# que es donde quiero hacer el merge.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git merge status 
    En la rama master
    nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="nv"&gt;$ &lt;/span&gt;git merge &lt;span class="nt"&gt;--no-ff&lt;/span&gt; feature/create-home 
    Merge made by the &lt;span class="s1"&gt;'recursive'&lt;/span&gt; strategy.
     home.css  | 3 +++
     home.html | 2 ++
     2 files changed, 5 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 home.css
     create mode 100644 home.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SBXWPEUW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgmhfk8vhr7od7vk5yjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SBXWPEUW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgmhfk8vhr7od7vk5yjc.png" alt="resultado integrar rama con merge commit" width="431" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Merge squash
&lt;/h3&gt;

&lt;p&gt;Condensar todos los commits de la rama a mergear en un único commit: &lt;code&gt;git merge --squash &amp;lt;rama&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Después del merge será necesario un hacer &lt;code&gt;git commit&lt;/code&gt;, cuyo mensaje por defecto será un sumario de todos los commits de &lt;code&gt;&amp;lt;rama&amp;gt;&lt;/code&gt;, aunque se podrá personalizar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Me aseguro de que estoy en la rama master, &lt;/span&gt;
&lt;span class="c"&gt;# que es donde quiero hacer el merge.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git merge status 
    En la rama master
    nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="nv"&gt;$ &lt;/span&gt;git merge &lt;span class="nt"&gt;--squash&lt;/span&gt; feature/create-home
    Actualizando 85b13b4..82975ee
    Fast-forward
    Commit de squash &lt;span class="nt"&gt;--&lt;/span&gt; no actualizando HEAD
     home.css  | 3 +++
     home.html | 2 ++
     2 files changed, 5 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 home.css
     create mode 100644 home.html

&lt;span class="nv"&gt;$ &lt;/span&gt;git commit 
    &lt;span class="o"&gt;[&lt;/span&gt;master 1a5ee55] Squashed commit of the following:
     2 files changed, 5 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 home.css
     create mode 100644 home.html

&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt;
    commit 1a5ee55ca09d28b8469385fa6675211ddc2d23ca &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt;

        Squashed commit of the following:

        commit 82975ee0f7f4fcab93e2b0d0d6e9d2f915510881     
            crear hoja de estilos home.css

        commit b9632f136aef8ae41306fc4468aa979800fb330a     
            crear home.html

    A       home.css
    A       home.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AbebLvqV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xe0mkjmutbgi2iqsx7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AbebLvqV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xe0mkjmutbgi2iqsx7o.png" alt="resultado integrar rama con merge squash" width="406" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Rebase
&lt;/h3&gt;

&lt;p&gt;Mover todos los commits de la rama a mergear en la rama actual, o, haciendo un símil, "replantar la rama": &lt;code&gt;git rebase &amp;lt;rama-destino&amp;gt; &amp;lt;rama-a-mover&amp;gt;&lt;/code&gt;.&lt;br&gt;
Si actualmente se está en &lt;code&gt;&amp;lt;rama-a-mover&amp;gt;&lt;/code&gt;, se puede hacer directamente &lt;code&gt;git rebase &amp;lt;rama-destino&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Después del merge será necesario un hacer &lt;code&gt;git merge&lt;/code&gt; para añadir los commits en la rama de integración.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dnHE2dXX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0c05kwa3yc6a1rhtumm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dnHE2dXX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0c05kwa3yc6a1rhtumm.png" alt="escenario integrar con rebase" width="403" height="252"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# "Replanto" feature/create-home en master.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git rebase master feature/create-home 
    En primer lugar, rebobinando HEAD para después reproducir 
        tus cambios encima de ésta...
    Aplicando: crear home.html
    Aplicando: crear hoja de estilos home.css

&lt;span class="c"&gt;# Hago checkout en master.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout master 
    Cambiado a rama &lt;span class="s1"&gt;'master'&lt;/span&gt;

&lt;span class="c"&gt;# Hago un merge fast forward de la rama a integrar.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git merge &lt;span class="nt"&gt;--ff-only&lt;/span&gt; feature/create-home 
    Actualizando e157378..d63cc7b
    Fast-forward
     log.txt | 2 ++
     1 file changed, 2 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mEm37G4K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mskuhl5r94505uq8s4ol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mEm37G4K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mskuhl5r94505uq8s4ol.png" alt="escenario integrar con rebase" width="378" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algo a tener en cuenta con &lt;code&gt;git rebase&lt;/code&gt; es que puede llegar a ser necesarios resolver conflictos  si  &lt;code&gt;&amp;lt;rama-a-mover&amp;gt;&lt;/code&gt; parte de un commit antiguo de &lt;code&gt;&amp;lt;rama-destino&amp;gt;&lt;/code&gt;. &lt;br&gt;
Si &lt;code&gt;&amp;lt;rama-a-mover&amp;gt;&lt;/code&gt; tiene varios commits puede llegar a ser necesario  resolver conflictos una vez por cada commit. &lt;br&gt;
Hay proyectos en los que por defecto utilizan &lt;code&gt;git rebase&lt;/code&gt;, y excepcionalmente,  cuando se encuentran un caso donde la resolución de conflictos se complica, usan &lt;code&gt;git merge&lt;/code&gt; para así solo resolver conflictos una única vez.&lt;/p&gt;

&lt;p&gt;Cuando surjan conflictos en un &lt;code&gt;git rebase&lt;/code&gt; seguir las instrucciones que da Git como salida del comando.&lt;/p&gt;
&lt;h3&gt;
  
  
  Trunk base development
&lt;/h3&gt;

&lt;p&gt;Sólo hay una rama, &lt;code&gt;master&lt;/code&gt;, y todos los commits se hacen sobre ella. &lt;br&gt;
Adelantándome al post de repositorios remotos, cuando se quiera subir esa rama al repositorio remoto y surjan conflictos porque la rama local &lt;code&gt;master&lt;/code&gt; ha divergido respecto de  la rama &lt;code&gt;master&lt;/code&gt; del repositorio remoto, habrá que decidir si optar por merge commits o por rebase.&lt;/p&gt;

&lt;p&gt;¿Por que se llama &lt;em&gt;Trunk base development&lt;/em&gt;? &lt;em&gt;Trunk&lt;/em&gt; es el nombre de la rama principal en los primeros sistemas de control de versiones.&lt;/p&gt;
&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Cada opción tiene sus pros y sus contras: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git merge&lt;/code&gt; preserva todo el histórico de commits tal y surgió, pero si no se sigue un buen flujo de ramas puede resultar en un árbol de commits muy complejo, donde sería difícil  determinar cuando se introdujo un bloque de código o un bug.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git merge --squash&lt;/code&gt; deja un árbol de commits muy sencillo, con una única rama y un único commit por cada feature, pero puede dejar commits muy grandes y se pierde información de los commits individuales.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git rebase&lt;/code&gt; produce una única rama con todos los commits que se han hecho, pero se pierde la información de en que punto se inicio una rama y los merges con conflictos pueden ser muy dolorosos.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Trunk base development&lt;/em&gt; reduce a 0 la gestión de ramas, pero cuando las ramas divergen hay que optar por &lt;code&gt;git merge&lt;/code&gt; o &lt;code&gt;git rebase&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Qué usar? La decisión dependerá de cuanta gente trabaje en el proyecto, de las convenciones del equipo,  del tipo de proyecto, de como de grandes sean las features, ... &lt;/p&gt;

&lt;p&gt;Esto intenta ser un post agnóstico, así que&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/B37cYPCruqwwg/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/B37cYPCruqwwg/giphy.gif" alt="bomba de humo" width="200" height="113"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  HEAD detached o desacoplado
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"git status" muestra un texto extraño en lugar del nombre de la rama; me he cambiado de rama y ya no encuentro el último commit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lo normal es hacer &lt;code&gt;git checkout&lt;/code&gt; a ramas, pero también se puede hacer a tags y a commits. En estos últimos casos se pasa al estado &lt;em&gt;"detached HEAD"&lt;/em&gt;, o &lt;em&gt;"HEAD desacoplada"&lt;/em&gt; si se tiene Git configurado en castellano .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'%C(auto)%h %s%n%C(auto)%d'&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; d63cc7b crear hoja de estilos home.css
    |  &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master, feature/create-home&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; 1676ceb crear home.html
    | 
    &lt;span class="k"&gt;*&lt;/span&gt; e157378 añadido .gitignore
    | 
    &lt;span class="k"&gt;*&lt;/span&gt; 85b13b4 &lt;span class="nb"&gt;set &lt;/span&gt;up proyecto
    | 
    &lt;span class="k"&gt;*&lt;/span&gt; 417ceac commit inicial

&lt;span class="c"&gt;# git status indica que estoy en la rama master.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    En la rama master
    nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# Al hacer checkout a un commit se muestra un mensaje &lt;/span&gt;
&lt;span class="c"&gt;# que da respeto.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout e157378
    Nota: cambiando a &lt;span class="s1"&gt;'e157378'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

    Te encuentras en estado &lt;span class="s1"&gt;'detached HEAD'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; Puedes revisar por aquí, hacer
    cambios experimentales y hacer commits, y puedes descartar cualquier
    commit que hayas hecho en este estado sin impactar a tu rama realizando
    otro checkout.

    Si quieres crear una nueva rama para mantener los commits que has creado,
    puedes hacerlo &lt;span class="o"&gt;(&lt;/span&gt;ahora o después&lt;span class="o"&gt;)&lt;/span&gt; usando &lt;span class="nt"&gt;-c&lt;/span&gt; con el comando checkout. Ejemplo:

      git switch &lt;span class="nt"&gt;-c&lt;/span&gt; &amp;lt;nombre-de-nueva-rama&amp;gt;

    O deshacer la operación con:

      git switch -

    Desactiva este aviso poniendo la variable de config advice.detachedHead en &lt;span class="nb"&gt;false

    &lt;/span&gt;HEAD está ahora en e157378 añadido .gitignore

&lt;span class="c"&gt;# git status en lugar de mostrar un nombre de rama &lt;/span&gt;
&lt;span class="c"&gt;# muestra un mensaje bastante raro....&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    HEAD desacoplada en e157378
    nada para hacer commit, el árbol de trabajo está limpio

&lt;span class="c"&gt;# git branch, para ver las ramas, también muestra &lt;/span&gt;
&lt;span class="c"&gt;# el mensaje raro.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch
    &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;HEAD desacoplada en e157378&lt;span class="o"&gt;)&lt;/span&gt;
      master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los checkouts a tag y a commits pueden ser una suerte de máquina del tiempo con la que, sin necesidad de crear o modificar ramas, poder consultar como estaba el código hace unas semanas, o confirmar que los tests funcionaban antes de integrar una feature.&lt;/p&gt;

&lt;p&gt;Para volver a ver nombres de ramas normales basta con hacer &lt;code&gt;git checkout&lt;/code&gt; a una rama.&lt;/p&gt;

&lt;p&gt;Los problemas pueden venir cuando estando en &lt;em&gt;detached HEAD&lt;/em&gt; se hace un commit y después  &lt;code&gt;git checkout&lt;/code&gt; a otra rama, ya que ese commit se puede llegar a perder a menos que se conozca su clave hash o se use &lt;code&gt;git reflog&lt;/code&gt; (ver &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b#borron-cuenta-nueva"&gt;Deshacer un commit: como revertir un cambio&lt;/a&gt; para más información sobre &lt;code&gt;git reflog&lt;/code&gt;).&lt;br&gt;
Si el commit es de prueba no habrá problema, ya que desaparecerá sin dejar rastro, pero si es algo con lo que se quiere seguir trabajando siempre es posible crear una rama a partir de él, o recuperarlo con &lt;code&gt;git cherry pick&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout e157378
    Nota: cambiando a &lt;span class="s1"&gt;'e157378'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

    Te encuentras en estado &lt;span class="s1"&gt;'detached HEAD'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; ...

&lt;span class="c"&gt;# Hago algunos cambios en el .gitignore.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"ignorar más cosas"&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;HEAD desacoplado aec5722] ignorar más cosas
     1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Cambio de rama por alguna razón y Git da la señal de&lt;/span&gt;
&lt;span class="c"&gt;# alarma, indicando ademas como se puede recuperar el commit.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout master 
    Peligro: estás saliendo 1 commit atrás, no está conectado
    a ninguna rama:

      aec5722 ignorar más cosas

    Si quieres conservarlo creando una nueva rama, este es un buen momento
    para hacerlo:

     git branch &amp;lt;nuevo-nombre-de-rama&amp;gt; aec5722

    Cambiado a rama &lt;span class="s1"&gt;'master'&lt;/span&gt;

&lt;span class="c"&gt;# Si por alguna razón no hubiese conservado el hash del&lt;/span&gt;
&lt;span class="c"&gt;# commit, siempre es posible consultarlo en con git reflog.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reflog 
    d63cc7b &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master, feature/create-home&lt;span class="o"&gt;)&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from aec57222a12d12ca6b87f5329ce67c10b5289d0a to master
    aec5722 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;: commit: ignorar más cosas
    e157378 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from master to e157378
    d63cc7b &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master, feature/create-home&lt;span class="o"&gt;)&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;3&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from e15737895b61e4c7e205a8729abad775b6679f5d to master
    e157378 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;4&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from master to e157378
    claudio@jupiter2:~/sandbox/git&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout e157378

&lt;span class="c"&gt;# Si quiero crear una rama para poder seguir trabajado a &lt;/span&gt;
&lt;span class="c"&gt;# partir de él,hago como ha dicho Git&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch nuevo-nombre-de-rama aec5722
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout feature/configure-project 
    Cambiado a rama &lt;span class="s1"&gt;'feature/configure-project'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    En la rama feature/configure-project
    nada para hacer commit, el árbol de trabajo está limpio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Si has llegado hasta aquí, gracias 🙂&lt;br&gt;
Espero que te haya resultado útil, y nos vemos en el próximo post sobre repositorios remotos 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  Créditos
&lt;/h2&gt;

&lt;p&gt;Cover: &lt;a href="https://pxhere.com/en/photo/149424"&gt;https://pxhere.com/en/photo/149424&lt;/a&gt;&lt;br&gt;
Generaciónd de diagramas: &lt;a href="https://excalidraw.com/"&gt;https://excalidraw.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>howto</category>
      <category>ramas</category>
      <category>introduccion</category>
    </item>
    <item>
      <title>Git: how to salir de esta, commits</title>
      <dc:creator>Claudio Sánchez</dc:creator>
      <pubDate>Tue, 15 Jun 2021 12:29:37 +0000</pubDate>
      <link>https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b</link>
      <guid>https://dev.to/narkha/git-how-to-salir-de-esta-commits-455b</guid>
      <description>&lt;h2&gt;
  
  
  How to
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introducción&lt;/li&gt;
&lt;li&gt;Cambiar el mensaje de un commit&lt;/li&gt;
&lt;li&gt;Deshacer un commit: cómo revertir un cambio&lt;/li&gt;
&lt;li&gt;Deshacer un commit: borrón y cuenta nueva&lt;/li&gt;
&lt;li&gt;Deshacer un git reset&lt;/li&gt;
&lt;li&gt;Añadir  o quitar algo de un commit&lt;/li&gt;
&lt;li&gt;Hacer commit con algunos cambios de un archivo, no del archivo completo&lt;/li&gt;
&lt;li&gt;Compartir archivos y cambios sin conflictos&lt;/li&gt;
&lt;li&gt;Cómo hacer un commit paso a paso&lt;br&gt;
¿o por qué no se ha añadido un archivo o un cambio al hacer commit?
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducción &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Los commits son la unidad básica de Git. Se identifican con una clave hash única y son inmutables, es decir, &lt;strong&gt;un commit no se puede modificar una vez creado&lt;/strong&gt;, pero es muy fácil reemplazarlo por otro con una clave hash diferente y  los cambios que se deseen.&lt;br&gt;
Dicho esto, y aunque se que lo correcto sería decir &lt;em&gt;"reemplazar el commit X por un commit X', que es como X pero con algunos cambios"&lt;/em&gt;, yo suelo decir &lt;em&gt;"modificar el commit X"&lt;/em&gt; porque es más corto y me abstrae de las complejidades de lo que hace Git por debajo; en el contexto de mi día a día prefiero un lenguaje conciso y expresivo, que transmita el resultado final, a una parrafada detallada y precisa que sea difícil de entender y donde sea fácil perderse en los detalles. &lt;/p&gt;

&lt;p&gt;Un ejemplo de clave hash sería &lt;code&gt;7f347041e695151cbe8493b8ed842949150095c4&lt;/code&gt;. Muchas veces, por no llenar la pantalla con claves largas, se suele usar la una clave abreviada, por ejemplo &lt;code&gt;7f34704&lt;/code&gt;, que vienen a ser los primeros caracteres de la clave hash. Nada garantiza que una clave abreviada sea única, pero si se detecta que esta repetida solo hay que mostrar más caracteres, hasta que deje de haber conflicto, por ejemplo &lt;code&gt;7f347041e&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Algo muy importante a tener en cuenta con los commits es que  &lt;strong&gt;no hay que modificar, deshacer o borrar  un commit que ya este en un repositorio remoto&lt;/strong&gt;, ya que otro desarrollador puede haber partido de ese commit para su desarrollo y cuando se quieran unir las dos versiones pueden surgir conflictos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cambiar el mensaje de un commit &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Corregir una falta de ortografía, mejorar el texto del commit,incluir la clave de la tarea del issue tracker, etc&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para modificar el mensaje de un commit lo más fácil es recurrir a un GUI, click derecho en el commit a modificar y click en la opción de editar el mensaje del commit.&lt;/p&gt;

&lt;p&gt;Para entender un poco lo que  pasa por debajo, además de saber como hacerlo cuando no se tiene una GUI, lo mejor es recurrir a la linea de comandos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Acabo de hacer un commit con un error en el texto.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"mi tercre commit"&lt;/span&gt; 
    &lt;span class="o"&gt;[&lt;/span&gt;master 7f34704] mi tercre commit
    1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Para cambiarlo&lt;/span&gt;

&lt;span class="c"&gt;# Primero me aseguro de que no haya ningún cambio en el área de stage.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    En la rama master
    Cambios a ser confirmados:
      &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git reset HEAD &amp;lt;archivo&amp;gt;..."&lt;/span&gt; para sacar del área de stage&lt;span class="o"&gt;)&lt;/span&gt;

        modificado:     dates.txt

&lt;span class="c"&gt;# Si los hay los saco del área de stage.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reset HEAD dates.txt 
    Cambios fuera del área de stage tras el reset:
    M   dates.txt

&lt;span class="c"&gt;# Y modifico el mensaje del commit.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"mi tercer commit"&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;master 19ffda6] mi tercer commit
     1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto habrá reemplazado el último commit, con hash &lt;code&gt;7f34704&lt;/code&gt;, por otro con el mismo contenido, pero con otro mensaje y hash &lt;code&gt;19ffda6&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cuando se usa &lt;code&gt;git commit --amend -m&lt;/code&gt;, es importante asegurarse qué se va a commitear para no incluir nada que se desee.&lt;/p&gt;

&lt;p&gt;Si se tuviese que modificar el mensaje de un commit más antiguo, por ejemplo el &lt;code&gt;077c45d&lt;/code&gt; , se podría hacer algo como esto&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# La virgulilla es importante&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; 077c45d~ 
&lt;span class="c"&gt;# Se abrirá un editor de texto con algo como&lt;/span&gt;
&lt;span class="c"&gt;##--------------&lt;/span&gt;
    pick 077c45d mi segunod commit
    pick 19ffda6 mi tercer commit

    &lt;span class="c"&gt;# Rebase bced58d..11a0995 en bced58d (2 comandos)&lt;/span&gt;
    &lt;span class="c"&gt;#&lt;/span&gt;
    &lt;span class="c"&gt;# Comandos:&lt;/span&gt;
    &lt;span class="c"&gt;#  p, pick = usar commit&lt;/span&gt;
    &lt;span class="c"&gt;#  r, reword = usar commit, pero editar el mensaje&lt;/span&gt;
      &lt;span class="c"&gt;#  .... &lt;/span&gt;
&lt;span class="c"&gt;## ----------------&lt;/span&gt;
&lt;span class="c"&gt;# Edito el archivo para tener&lt;/span&gt;
    r 077c45d mi segundo commit
    pick 19ffda6 mi tercer commit
&lt;span class="c"&gt;## Guardo.&lt;/span&gt;
&lt;span class="c"&gt;## Se abre un editor de texto con el mensaje a modificar, &lt;/span&gt;
&lt;span class="c"&gt;## escribo el texto correcto y guardo.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto habrá remplazado el commit &lt;code&gt;077c45d&lt;/code&gt;, por otro con  el mensaje correcto y un nuevo hash, así como  todos los commits que vengan después.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; 52190c2 mi tercer commit
    &lt;span class="k"&gt;*&lt;/span&gt; 247f469 mi segundo commit
    &lt;span class="k"&gt;*&lt;/span&gt; bced58d first commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aunque ni el contenido ni el mensaje del commit con hash &lt;code&gt;19ffda6&lt;/code&gt; hayan cambiado, si ha cambiado el commit que venía antes que él, y por lo tanto ha hecho falta reemplazarlo para reflejar ese cambio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deshacer un commit: cómo revertir un cambio &lt;a&gt;&lt;/a&gt;&lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Un commit que produce un bug; un commit hecho por error; un commit con trazas hecho por error; etc&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cuando lo que se quiere deshacer esta bien acotado en un commit, y se está seguro de que si ese commit desapareciese todo estaría como debería, se puede usar &lt;code&gt;git revert &amp;lt;hash a deshacer&amp;gt;&lt;/code&gt;, o en el GUI, click derecho en el commit a deshacer, y &lt;em&gt;"Revert commit"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git revert&lt;/code&gt; no elimina el commit objetivo, si no que crea un commit con cambios para deshacer el commit objetivo.&lt;/p&gt;

&lt;p&gt;¿Y si se quiere deshacer el commit resultado de un &lt;code&gt;git revert&lt;/code&gt;? Se puede hacer un &lt;code&gt;git revert&lt;/code&gt; de ese commit.&lt;/p&gt;

&lt;p&gt;¿Y si no se quiere deshacer el commit entero, si no sólo parte?&lt;br&gt;
En algunos GUIs,  &lt;em&gt;"Revert commit"&lt;/em&gt;  abrirá una ventana con los cambios del &lt;em&gt;revert commit&lt;/em&gt;; si se cierra esa ventana, se podrá: ver cambios del &lt;em&gt;"revert commit"&lt;/em&gt;; añadir o quitar cosas; y finalmente hacer un nuevo commit.&lt;br&gt;
Por consola lo equivalente sería &lt;code&gt;git revert --no-commit &amp;lt;hash a deshacer&amp;gt;&lt;/code&gt;, revisar el &lt;em&gt;"revert commit"&lt;/em&gt; y &lt;code&gt;git commit&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; 73d8766 &lt;span class="nt"&gt;--patch-with-stat&lt;/span&gt; 
    commit 73d8766f13198c5da71e2759b1c659f5c5a3bf8a &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt;
        commit con error
    &lt;span class="nt"&gt;---&lt;/span&gt;
     log.txt | 1 +
     1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

    diff &lt;span class="nt"&gt;--git&lt;/span&gt; a/log.txt b/log.txt
    index f14e7df..7c5c54a 100644
    &lt;span class="nt"&gt;---&lt;/span&gt; a/log.txt
    +++ b/log.txt
    @@ &lt;span class="nt"&gt;-1&lt;/span&gt;,5 +1,6 @@
     dom may 24 16:17:36 CEST 2020: log
    +esto no es un log
     dom may 24 16:17:37 CEST 2020: log

&lt;span class="nv"&gt;$ &lt;/span&gt;git revert 73d8766
    &lt;span class="o"&gt;[&lt;/span&gt;master e9bac4c] Revert &lt;span class="s2"&gt;"commit con error"&lt;/span&gt;
     1 file changed, 1 deletion&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; e9bac4c &lt;span class="nt"&gt;--patch-with-stat&lt;/span&gt;
    commit e9bac4c003bc41640c29a12b21b70a5eb0d99193 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt;
        Revert &lt;span class="s2"&gt;"commit con error"&lt;/span&gt;     
        This reverts commit 73d8766f13198c5da71e2759b1c659f5c5a3bf8a.
    &lt;span class="nt"&gt;---&lt;/span&gt;
     log.txt | 1 -
     1 file changed, 1 deletion&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;

    diff &lt;span class="nt"&gt;--git&lt;/span&gt; a/log.txt b/log.txt
    index 7c5c54a..f14e7df 100644
    &lt;span class="nt"&gt;---&lt;/span&gt; a/log.txt
    +++ b/log.txt
    @@ &lt;span class="nt"&gt;-1&lt;/span&gt;,6 +1,5 @@
     dom may 24 16:17:36 CEST 2020: log
    &lt;span class="nt"&gt;-esto&lt;/span&gt; no es un log
     dom may 24 16:17:37 CEST 2020: log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Y si el commit es de un &lt;em&gt;merge commit&lt;/em&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git revert 5139b956
    error: el commit 5139b9560d954dd0c20320ecb3bac404e8bee7dc es una fusión pero no se proporcionó la opción &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
    fatal: falló al revertir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El comando dará un error, el cual se verá en el &lt;a href="https://dev.to/narkha/git-how-to-salir-de-esta-ramas-4f74#deshacer-un-merge"&gt;post dedicado a ramas&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deshacer un commit: borrón y cuenta nueva &lt;a&gt;&lt;/a&gt;&lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Empezar desde de cero una feature que se está complicando; estar a medias en una resolución de conflictos de un merge, perder el hilo por alguna razón, y casi que mejor empezar de 0 ; etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git reset &amp;lt;hash&amp;gt;&lt;/code&gt;  hará que todo sea como en el commit de indicado, incluido el histórico de commits. &lt;br&gt;
¿Qué pasara con las diferencias que hay entre el commit actual y el commit de destino? Bien, &lt;code&gt;git revert&lt;/code&gt; tiene varios modos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--soft&lt;/code&gt; deja todos los cambios como &lt;em&gt;staged&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--mixed&lt;/code&gt; (el modo por defecto) deja todos los cambios como &lt;em&gt;unstage&lt;/em&gt; o &lt;em&gt;untracked&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--hard&lt;/code&gt; descarta todos los cambios. Hay que intentar hacerlo solo cuando se este seguro, porque no siempre es posible recuperar todos los cambios. Para más detalles ver Deshacer un git reset.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--merge&lt;/code&gt;, nunca he llegado a entenderlo...&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--keep&lt;/code&gt;, nunca he llegado a entenderlo...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si se usa un GUI, la diferencia entre &lt;code&gt;--soft&lt;/code&gt; y &lt;code&gt;--mixed&lt;/code&gt; no es apreciable, ya que el GUI hace su magia por debajo y el resultado final es el mismo; si se usa consola, con &lt;code&gt;--soft&lt;/code&gt; se podría hacer directamente un commit con todos los cambios, sin tener que añadir los archivos con &lt;code&gt;git add&lt;/code&gt;, mientras que con &lt;code&gt;--mixed&lt;/code&gt; si habría que hacerlo.&lt;/p&gt;

&lt;p&gt;Para hacerlo desde un GUI, click derecho en el commit al que se desee volver y click en &lt;em&gt;"Reset current branch to Here..."&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Por consola:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Consulto el histórico de commits.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; b2cd87b mi tercer commit
    &lt;span class="k"&gt;*&lt;/span&gt; 247f469 mi segundo commit
    &lt;span class="k"&gt;*&lt;/span&gt; bced58d first commit

&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; bced58d
    HEAD is now at bced58d reset

&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; bced58d first commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para los usuarios de consola, y adelantando un poco contenidos del futuro post de ramas, decir que se pueden hacer cosas como &lt;code&gt;git reset master&lt;/code&gt;, para así hacer que el commit de destino sea el último commit de la rama &lt;em&gt;master&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deshacer un git reset &lt;a&gt;&lt;/a&gt;&lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;He hecho 'git reset —hard' donde no era y he perdido todos los cambios; He hecho 'git reset'  al commit donde no era y he perdido algunos cambios.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cuando se hace &lt;code&gt;git reset --hard&lt;/code&gt;  se pueden perder dos cosas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commits que no estén en ninguna otra rama.&lt;/li&gt;
&lt;li&gt;Cambios de los que todavía no se hubiese hecho ningún commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo primero tiene solución haciendo otro &lt;code&gt;git reset&lt;/code&gt; al punto del que que se venía&lt;br&gt;
¿Pero y si no se conoce el hash del commit al que se quiere volver?&lt;br&gt;
&lt;code&gt;git reflog&lt;/code&gt; muestra un histórico de todos los commits por los que sea ha pasado, ya sea porque se ha hecho un commit, se ha cambiado de rama, o se ha hecho un &lt;code&gt;git reset&lt;/code&gt;. &lt;br&gt;
Un ejemplo sería&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fc2f7e1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;: commit: amazing stuff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fc2f7e1&lt;/code&gt;: es el hash del commit por el que se ha pasado.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HEAD@{1}&lt;/code&gt;: es un alias algo más amigable de ese hash. El indice indica hace cuando se produjo el cambio, siendo &lt;code&gt;HEAD{0}&lt;/code&gt; el punto actual, &lt;code&gt;HEAD{1}&lt;/code&gt;  el punto anterior, &lt;code&gt;HEAD{2}&lt;/code&gt; lo que vino antes, etc.
Estos alias no son constantes, si por ejemplo se hiciese otro &lt;code&gt;git reset&lt;/code&gt; u otro &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;HEAD{1}&lt;/code&gt; pasaría a referenciar lo que referenciase &lt;code&gt;HEAD{0}&lt;/code&gt; antes del cambio y sucesivamente.&lt;/li&gt;
&lt;li&gt;acción: en este caso commit, pero podría ser un reset, un checkout, un merge, etc.&lt;/li&gt;
&lt;li&gt;mensaje: una descripción textual de la acción.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Poniéndolo en un ejemplo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Partiendo de un repositorio a estrenar.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; 00fd1f0 inicializar repo

&lt;span class="c"&gt;# Hago algunos cambios en el proyecto y hago commit.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"amazing stuff"&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;master fc2f7e1] amazing stuff
     1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, 1 deletion&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Hago un git reset por alguna razón.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; 00fd1f0
    HEAD is now at 00fd1f0 inicializar repo

&lt;span class="c"&gt;# Reviso el histórico y me doy cuenta de que he perdido &lt;/span&gt;
&lt;span class="c"&gt;# cosas por error.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; 00fd1f0 inicializar repo

&lt;span class="nv"&gt;$ &lt;/span&gt;git reflog 
    00fd1f0 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;: reset: moving to 00fd1f0
    fc2f7e1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;: commit: amazing stuff
    00fd1f0 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}&lt;/span&gt;: commit &lt;span class="o"&gt;(&lt;/span&gt;initial&lt;span class="o"&gt;)&lt;/span&gt;: inicializar repo

&lt;span class="c"&gt;# Hago reset al punto al que quiero volver.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;
    HEAD is now at fc2f7e1 amazing stuff

&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; fc2f7e1 amazing stuff
    &lt;span class="k"&gt;*&lt;/span&gt; 00fd1f0 inicializar repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Y si es el segundo caso?&lt;br&gt;
En esos casos me apoyo en el IDE, ya que desconozco si hay alguna manera de hacerlo con Git.&lt;/p&gt;

&lt;p&gt;La mayoría de los IDEs suelen tener un &lt;em&gt;"Local history"&lt;/em&gt; donde almacenan todos los cambios que se han hecho, y se puede acceder a él para ver cuando se produjo un cambio o restaurar algo.&lt;br&gt;
Para acceder suele ser algo como como seleccionar una carpeta o un archivo en el IDE, click derecho, &lt;em&gt;"Local history"&lt;/em&gt;, &lt;em&gt;"Show history"&lt;/em&gt; y a jugar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sj4jyi93--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4qh9iz8pix0egy9zcfwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sj4jyi93--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4qh9iz8pix0egy9zcfwm.png" alt="historial local IDE" width="880" height="300"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Añadir o quitar algo de un commit &lt;a&gt;&lt;/a&gt;&lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Añadir un archivo que por alguna razón se ha olvidado, quitar algo que se ha olvidado quitar; quitar algo que se ha commiteado por error, etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;La solución más sencilla es hacer un nuevo commit con lo que se quiere añadir o quitar, y la mejor si ha se ha hecho &lt;code&gt;git push&lt;/code&gt; ; quedará un commit de más en la rama (se si usa &lt;code&gt;git merge--squash&lt;/code&gt; ni siquiera eso), pero es una solución rápida y a prueba de errores.&lt;/p&gt;

&lt;p&gt;Ahora bien, si eres de esos a los que les gusta tener un árbol de commits donde cada uno de ellos represente un paso lógico dado para crear una nueva feature, para así tener un histórico bien detallado, hay comandos para modificar los commits.&lt;/p&gt;

&lt;p&gt;Si se usa una GUI, en el menú del commit suele existir la opción de &lt;em&gt;"Amend Commit"&lt;/em&gt;, que a grandes grandes rasgos crea un nuevo commit con la unión del último commit de la rama y el commit que se esté haciendo y  reemplazará el último commit de la rama con ese nuevo commit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Antes del "Amend commit".&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; b2cd87b mi tercer commit
    &lt;span class="k"&gt;*&lt;/span&gt; 247f469 mi segundo commit
    &lt;span class="k"&gt;*&lt;/span&gt; bced58d first commit

&lt;span class="c"&gt;# Después del "Amend commit".&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%h %s"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; d9822c9 mi tercer commit
    &lt;span class="k"&gt;*&lt;/span&gt; 247f469 mi segundo commit
    &lt;span class="k"&gt;*&lt;/span&gt; bced58d first commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para hacerlo en consola&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Modificao un archivo.&lt;/span&gt;

&lt;span class="c"&gt;# Revisar el status.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    En la rama master
    Cambios no rastreados para el commit:
      &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git add &amp;lt;archivo&amp;gt;..."&lt;/span&gt; para actualizar lo que será confirmado&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;(&lt;/span&gt;usa &lt;span class="s2"&gt;"git checkout -- &amp;lt;archivo&amp;gt;..."&lt;/span&gt; para descartar los cambios en el directorio de trabajo&lt;span class="o"&gt;)&lt;/span&gt;

        modificado:     dates.txt

&lt;span class="c"&gt;# Añado el archivo modificado al área de stage.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git add dates.txt

&lt;span class="c"&gt;# Hago un commit con la opción ammend para modificar &lt;/span&gt;
&lt;span class="c"&gt;# el commit y el mensaje.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"mi tercer commit más un cambio"&lt;/span&gt;                     
    &lt;span class="o"&gt;[&lt;/span&gt;master d9822c9] mi tercer commit más un cambio
     1 file changed, 2 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Y si el commit no es el último, si no uno anterior?&lt;br&gt;
&lt;code&gt;git rebase -i&lt;/code&gt; (ver Cambiar el mensaje de un commit, a parte de &lt;em&gt;pick&lt;/em&gt; y &lt;em&gt;reword&lt;/em&gt; tiene la opción de editar o borrar un commit. Es una opción que existe, pero intento evitarla ya que es probable que implique resolver conflictos varias veces: si se edita un archivo en un commit antiguo, es probable que ese mismo archivo haya sido editado commits posteriores y habrá resolver conflictos por cada uno de esos commits.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hacer commit con algunos cambios de un archivo, no del archivo completo &lt;a&gt;&lt;/a&gt;&lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Estoy con un bug y creo que ya lo he solucionado, así que voy probarlo en la máquina de CI; por si acaso no quiero borrar todavía las trazas de debug que he metido, pero tampoco quiero hacer un commit con ellas.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Algunos GUIs dejan revisar que cambios en un archivo se quieren commitear al inspeccionar los archivos para el commit&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cBPvYvHL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/blfay7h6rtpclieoas0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cBPvYvHL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/blfay7h6rtpclieoas0e.png" alt="Inspeccionar commit en IDE" width="880" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Desde consola también se puede hacer  con &lt;code&gt;git add -p&lt;/code&gt; (o &lt;code&gt;--patch&lt;/code&gt;) y seleccionar que trozos de un archivo se quieren añadir; o con &lt;code&gt;git commit -i&lt;/code&gt; (o &lt;code&gt;--interactive&lt;/code&gt;) , que permite elegir como tratar todos los archivos que se incluirían en el commit al hacer &lt;code&gt;git commit -a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Estos comandos abren un dialogo en la consola donde se puede seleccionar como tratar los cambios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nt"&gt;-p&lt;/span&gt; recursive.php 
    diff &lt;span class="nt"&gt;--git&lt;/span&gt; a/recursive.php b/recursive.php
    index 215ddd0..590b3ac 100644
    &lt;span class="nt"&gt;---&lt;/span&gt; a/recursive.php
    +++ b/recursive.php
    @@ &lt;span class="nt"&gt;-1&lt;/span&gt;,11 +1,14 @@
     &amp;lt;?php

         &lt;span class="k"&gt;function &lt;/span&gt;recursiveFunction&lt;span class="o"&gt;(&lt;/span&gt;Closure &lt;span class="nv"&gt;$action&lt;/span&gt;, Closure &lt;span class="nv"&gt;$stopCheck&lt;/span&gt;, &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; : void &lt;span class="o"&gt;{&lt;/span&gt;
    +        var_dump&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    +
             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$stopCheck&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    +            var_dump&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"stop contidion matched"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                 &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
             &lt;span class="o"&gt;}&lt;/span&gt;

    -        &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    +        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

             recursiveFunction&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;, &lt;span class="nv"&gt;$stopCheck&lt;/span&gt;, &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="se"&gt;\ &lt;/span&gt;No newline at end of file
    Stage this hunk &lt;span class="o"&gt;[&lt;/span&gt;y,n,q,a,d,s,e,?]? ?    
    y - stage this hunk
    n - &lt;span class="k"&gt;do &lt;/span&gt;not stage this hunk
    q - quit&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;not stage this hunk or any of the remaining ones
    a - stage this hunk and all later hunks &lt;span class="k"&gt;in &lt;/span&gt;the file
    d - &lt;span class="k"&gt;do &lt;/span&gt;not stage this hunk or any of the later hunks &lt;span class="k"&gt;in &lt;/span&gt;the file
    s - &lt;span class="nb"&gt;split &lt;/span&gt;the current hunk into smaller hunks
    e - manually edit the current hunk
    ? - print &lt;span class="nb"&gt;help
    &lt;/span&gt;Stage this hunk &lt;span class="o"&gt;[&lt;/span&gt;y,n,q,a,d,s,e,?]? s
    Split into 3 hunks.
    @@ &lt;span class="nt"&gt;-1&lt;/span&gt;,4 +1,6 @@
     &amp;lt;?php

         &lt;span class="k"&gt;function &lt;/span&gt;recursiveFunction&lt;span class="o"&gt;(&lt;/span&gt;Closure &lt;span class="nv"&gt;$action&lt;/span&gt;, Closure &lt;span class="nv"&gt;$stopCheck&lt;/span&gt;, &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; : void &lt;span class="o"&gt;{&lt;/span&gt;
    +        var_dump&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    +
             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$stopCheck&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    Stage this hunk &lt;span class="o"&gt;[&lt;/span&gt;y,n,q,a,d,j,J,g,/,e,?]? n
    @@ &lt;span class="nt"&gt;-4&lt;/span&gt;,4 +6,5 @@
             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$stopCheck&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    +            var_dump&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"stop contidion matched"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                 &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
             &lt;span class="o"&gt;}&lt;/span&gt;

    Stage this hunk &lt;span class="o"&gt;[&lt;/span&gt;y,n,q,a,d,K,j,J,g,/,e,?]? n
    @@ &lt;span class="nt"&gt;-5&lt;/span&gt;,7 +8,7 @@
                 &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
             &lt;span class="o"&gt;}&lt;/span&gt;

    -        &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    +        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

             recursiveFunction&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;, &lt;span class="nv"&gt;$stopCheck&lt;/span&gt;, &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="se"&gt;\ &lt;/span&gt;No newline at end of file
    Stage this hunk &lt;span class="o"&gt;[&lt;/span&gt;y,n,q,a,d,K,g,/,e,?]? y

&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch &lt;span class="nb"&gt;test
    &lt;/span&gt;Changes to be committed:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git reset HEAD &amp;lt;file&amp;gt;..."&lt;/span&gt; to unstage&lt;span class="o"&gt;)&lt;/span&gt;

            modified:   recursive.php

    Changes not staged &lt;span class="k"&gt;for &lt;/span&gt;commit:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add &amp;lt;file&amp;gt;..."&lt;/span&gt; to update what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git checkout -- &amp;lt;file&amp;gt;..."&lt;/span&gt; to discard changes &lt;span class="k"&gt;in &lt;/span&gt;working directory&lt;span class="o"&gt;)&lt;/span&gt;

            modified:   recursive.php

&lt;span class="nv"&gt;$ &lt;/span&gt;git diff &lt;span class="nt"&gt;--staged&lt;/span&gt; 
    diff &lt;span class="nt"&gt;--git&lt;/span&gt; a/recursive.php b/recursive.php
    index 215ddd0..b865da0 100644
    &lt;span class="nt"&gt;---&lt;/span&gt; a/recursive.php
    +++ b/recursive.php
    @@ &lt;span class="nt"&gt;-5&lt;/span&gt;,7 +5,7 @@
                 &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
             &lt;span class="o"&gt;}&lt;/span&gt;

    -        &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    +        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

             recursiveFunction&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;, &lt;span class="nv"&gt;$stopCheck&lt;/span&gt;, &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="se"&gt;\ &lt;/span&gt;No newline at end of file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y permite ir tan al detalle como seleccionar que lineas concretas de un pedazo de código se quieren incluir en el commit, opción que no todos los GUI permiten.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L4XdEbal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szpr09ydvyt647he98ya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L4XdEbal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szpr09ydvyt647he98ya.png" alt="IDE seleccionar pedazo" width="880" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compartir archivos y cambios sin conflictos&lt;a&gt;&lt;/a&gt;&lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Traerme de otra rama en desarrollo una nueva interfaz, un cambio o un fix; etc&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Si los cambios estuviesen ya en &lt;em&gt;master&lt;/em&gt;, o en cualquier otra rama compartida, sería tan sencillo como mergear esa rama, pero hay ocasiones en las que dos desarrolladores (pongamos Fulano y Mengano) están trabajando cada uno en su rama y la cosa se complica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fulano podría mergearse la rama de Mengano, pero ello implicaría traerse también cosas todavía no estables o no finalizadas, y a la larga le podría dar problemas.&lt;/li&gt;
&lt;li&gt;Fulano podría pedirle por email o chat los cambios a Mengano y aplicarlos manualmente en su rama.&lt;/li&gt;
&lt;li&gt;O Fulano, si Mengano hubiese subido su rama al repositorio común, podría usar &lt;code&gt;git cherry-pick&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git cherry-pick &amp;lt;hash&amp;gt;&lt;/code&gt; crea un commit que añade exactamente los mismos objetos que los que contiene el commit indicado (para más información ahí va &lt;a href="https://aboullaite.me/deep-dive-into-git/"&gt;un buen artículo&lt;/a&gt; de como se organiza Git por debajo).&lt;/p&gt;

&lt;p&gt;Si hay un commit que sólo contiene los cambios que se desea traer (una nueva interfaz, clase, archivo, fix, etc), es sencillo.&lt;/p&gt;

&lt;p&gt;Desde el GUI, buscar el commit con los cambios, click derecho, y &lt;em&gt;"Cherry-Pick"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Desde consola &lt;code&gt;git cherry-pick -x &amp;lt;hash&amp;gt;&lt;/code&gt;  ( &lt;code&gt;-x&lt;/code&gt; añade al commit el texto &lt;code&gt;cherry picked from commit &amp;lt;hash&amp;gt;&lt;/code&gt;, lo cual puede ser un buen añadido)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# La rama amazing contiene una una interfaz que &lt;/span&gt;
&lt;span class="c"&gt;# quiero traerme.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;amazing&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-2&lt;/span&gt; &lt;span class="nt"&gt;--stat&lt;/span&gt; 
    commit c30dd31081fc390465d9ef1a7f3d0a8422d90408 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; amazing&lt;span class="o"&gt;)&lt;/span&gt;

        AMAZING: implementación en proceso

     src/AmazingImplementation.php | 10 ++++++++++
     1 file changed, 10 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

    commit e10c9b91860d182b4985c843a502de653e44c500

        AMAZING: new inteface

     src/AmazingInterface.php | 7 +++++++
     1 file changed, 7 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Mi rama actual es comercial, y me traigo los cambios &lt;/span&gt;
&lt;span class="c"&gt;# que me interesan.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;comercial&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git cherry-pick &lt;span class="nt"&gt;-x&lt;/span&gt; e10c9b91860d182b4985c843a502de653e44c500
    &lt;span class="o"&gt;[&lt;/span&gt;comercial 1ef28f9] AMAZING: new inteface
     1 file changed, 7 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 src/AmazingInterface.php

&lt;span class="c"&gt;# Hago algún otro commit.&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-2&lt;/span&gt; &lt;span class="nt"&gt;--stat&lt;/span&gt; 
    commit f55e27bb46ae08c6dfb97a69e3f9ab4dc2ef18e3 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; comercial&lt;span class="o"&gt;)&lt;/span&gt;

        COMERCIAL: Comercial.php

     src/Comercial.php | 15 +++++++++++++++
     1 file changed, 15 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

    commit 1ef28f9e31adb6d6191d1b2f224daf5357dd217d

        AMAZING: new inteface

        &lt;span class="o"&gt;(&lt;/span&gt;cherry picked from commit e10c9b91860d182b4985c843a502de653e44c500&lt;span class="o"&gt;)&lt;/span&gt;

     src/AmazingInterface.php | 7 +++++++
     1 file changed, 7 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cuando en el futuro se haga el merge no debería &lt;/span&gt;
&lt;span class="c"&gt;# haber conflictos...&lt;/span&gt;
&lt;span class="c"&gt;# a menos que se hayan tocado mucho los archivos en &lt;/span&gt;
&lt;span class="c"&gt;# las dos ramas.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git merge &lt;span class="nt"&gt;--no-ff&lt;/span&gt; amazing 
    Merge made by the &lt;span class="s1"&gt;'recursive'&lt;/span&gt; strategy.
     src/AmazingImplementation.php | 10 ++++++++++
     src/AmazingInterface.php      |  7 +++++++
     2 files changed, 17 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 src/AmazingImplementation.php
     create mode 100644 src/AmazingInterface.php

&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git merge &lt;span class="nt"&gt;--no-ff&lt;/span&gt; comercial
    Merge made by the &lt;span class="s1"&gt;'recursive'&lt;/span&gt; strategy.
     src/AmazingInterface.php |  1 +
     src/Comercial.php        | 15 +++++++++++++++
     2 files changed, 16 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 src/Comercial.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Algo a tener en cuenta a la hora de hacer &lt;code&gt;cherry-pick&lt;/code&gt; de archivos que no están en la rama, es que si por ejemplo ese archivo se ha creado en un commit y modificado en otro, y se intenta hacer &lt;code&gt;cherry-pick&lt;/code&gt; de ese último commit, se producirá un conflicto.&lt;br&gt;
Se puede resolver el conflicto o hacer &lt;code&gt;git cherry-pick -x &amp;lt;hash-primer-commit&amp;gt; &amp;lt;hash-segundo-commit&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;¿Qué ocurre si &lt;code&gt;&amp;lt;hash-commit-X&amp;gt;&lt;/code&gt; contiene cambios que no queremos, como por ejemplo la clase que implementa la interfaz que queremos traernos?&lt;/p&gt;

&lt;p&gt;Desde consola se puede hacer &lt;code&gt;git cherry-pick -x --no-commit &amp;lt;hash-commit-X&amp;gt;&lt;/code&gt; , que lo dejara todo listo para hacer el commit. En ese momento se podría quitar alguno de los archivos que no se quisiesen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Hay una rama que en uno de sus commits tiene la interfaz&lt;/span&gt;
&lt;span class="c"&gt;# que me interesa junto con más cosas.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-2&lt;/span&gt; &lt;span class="nt"&gt;--stat&lt;/span&gt;
    commit dbcf29746184e8d9d3969fc4e008a80f140d7df6 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; amazing-II&lt;span class="o"&gt;)&lt;/span&gt;

        implementación de método

     src/AmazingImplementation.php | 10 ++++++++++
     1 file changed, 10 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;

    commit 61b38431b7b6cdcc279515b3467370d1d8cd64ca

        añadida interfaz y algo más

     log.txt                  | 3 +++
     src/AmazingInterface.php | 6 ++++++
     2 files changed, 9 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Estoy en la rama comercial-II, y me quiero traer &lt;/span&gt;
&lt;span class="c"&gt;# la interfaz&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;comercial-II&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git cherry-pick &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;--no-commit&lt;/span&gt; 61b38431b7b6cdcc279515b3467370d1d8cd64ca

&lt;span class="c"&gt;# Reviso los cambios.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;comercial-II&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch comercial-II
    Changes to be committed:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git reset HEAD &amp;lt;file&amp;gt;..."&lt;/span&gt; to unstage&lt;span class="o"&gt;)&lt;/span&gt;

            modified:   log.txt
            new file:   src/AmazingInterface.php

&lt;span class="c"&gt;# Quito los cambios que no necesito.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;comercial-II&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git reset HEAD log.txt
    Unstaged changes after reset:
    M       log.txt

&lt;span class="c"&gt;# Hago el commit.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;comercial-II&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"añadida solo interfaz"&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;comercial-II 16908dd] añadida solo interfaz
     1 file changed, 6 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 src/AmazingInterface.php

&lt;span class="c"&gt;# Reviso el status, donde veo que tengo cambios que no he &lt;/span&gt;
&lt;span class="c"&gt;# commiteado y que tendré que quitar.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;comercial-II&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch comercial-II
    Changes not staged &lt;span class="k"&gt;for &lt;/span&gt;commit:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add &amp;lt;file&amp;gt;..."&lt;/span&gt; to update what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git checkout -- &amp;lt;file&amp;gt;..."&lt;/span&gt; to discard changes &lt;span class="k"&gt;in &lt;/span&gt;working directory&lt;span class="o"&gt;)&lt;/span&gt;

            modified:   log.txt

    no changes added to commit &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add"&lt;/span&gt; and/or &lt;span class="s2"&gt;"git commit -a"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Reviso los cambios que he incluido en el commit.&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;comercial-II&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--stat&lt;/span&gt; 
    commit 16908dd4cf9d15e2bf8feafce1d1b3e296f1bede &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; comercial-II&lt;span class="o"&gt;)&lt;/span&gt;
    Author: claudio &amp;lt;claudio.sanchez@coches.com&amp;gt;
    Date:   Sun Aug 23 13:32:11 2020 +0200

        añadida solo interfaz

        &lt;span class="o"&gt;(&lt;/span&gt;edited cherry picked from commit 61b38431b7b6cdcc279515b3467370d1d8cd64ca&lt;span class="o"&gt;)&lt;/span&gt;

     src/AmazingInterface.php | 6 ++++++
     1 file changed, 6 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;También se puede hacer &lt;code&gt;cherry-pick&lt;/code&gt; de rangos de commits&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# la ~ en el primer commit es importante&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git cherry-pick &lt;span class="nt"&gt;-x&lt;/span&gt; &amp;lt;hash-primer-commit&amp;gt;~..&amp;lt;hash-ultimo-commit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cómo hacer un commit paso a paso&lt;br&gt;¿o por qué no se ha añadido un archivo o un cambio al hacer commit? &lt;a&gt;&lt;/a&gt;&lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EkqZZomh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6tnf8wlhoz6ccjir2p4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EkqZZomh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6tnf8wlhoz6ccjir2p4.png" alt="ciclo commit" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Por qué un cambio o un nuevo archivo no pueden llegar a incluirse en un commit al hacer &lt;code&gt;git commit&lt;/code&gt;? &lt;/p&gt;

&lt;p&gt;Podría ser porque el archivo está &lt;em&gt;untracked,&lt;/em&gt; porque se ha hecho &lt;code&gt;git commit&lt;/code&gt; cuando el archivo no estaba en área de &lt;em&gt;stage&lt;/em&gt; o porque cumple alguna de las expresiones del archivo &lt;code&gt;.gitignore&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Para entender la respuesta a los dos primeros casos hay que entender cómo es el ciclo de vida de un archivo en Git y hacer un commit siguiendo todos los pasos, sin atajos como &lt;code&gt;git commit -a&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Para Git los archivos pueden estar en dos estados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Tracked&lt;/em&gt;: son todos aquellos archivos sobre los que Git lleva un registro, y que alguien tendría si se clonase el repositorio.
Los archivos en este estado pueden estar a su vez modificados, no modificados o en el area de &lt;em&gt;stage&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Untracked&lt;/em&gt;: son todos aquellos archivos que están dentro de la carpeta del repositorio pero que nunca se le ha dicho a Git que tiene que registrar.
Git no hace nada que no se le diga, así que un archivo &lt;em&gt;untracked&lt;/em&gt; estará así hasta que se indique explícitamente que debe cambiar al estado &lt;em&gt;tracked&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A grandes rasgos, cuando se crea un nuevo archivo en la carpeta del repositorio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El archivo empieza en el estado &lt;em&gt;untracked&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Con &lt;code&gt;git add &amp;lt;nuevo archivo&amp;gt;&lt;/code&gt;  se le dice a Git que lo tiene que registrar; el archivo pasara a estar en el estado  &lt;em&gt;tracked&lt;/em&gt; y se moverá al área de &lt;em&gt;stage&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Cuando se haga &lt;code&gt;git commit&lt;/code&gt; se incluirá en el nuevo commit, se sacará del área de &lt;em&gt;stage&lt;/em&gt; y pasará a estar no modificado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Un detalle importante, es que &lt;code&gt;git commit -a&lt;/code&gt; no registra archivos en estado &lt;em&gt;untracked&lt;/em&gt;, y por lo tanto estos no se incluirían en el commit. Hay que incluirlo con &lt;code&gt;git add&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;¿Y cuando se modifica o borra un archivo que ya estaba registrado?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El archivo pasa a estar como modificado.&lt;/li&gt;
&lt;li&gt;Con &lt;code&gt;git add &amp;lt;nuevo archivo&amp;gt;&lt;/code&gt;  se moverá al área de &lt;em&gt;stage&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Con &lt;code&gt;git commit&lt;/code&gt;  se incluirá en el nuevo commit, se sacará del área de &lt;em&gt;stage&lt;/em&gt; y pasará a estar no modificado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para archivos en estado &lt;em&gt;tracked&lt;/em&gt; si funciona &lt;code&gt;git commit -a&lt;/code&gt;, así que es posible ahorrarse el &lt;code&gt;git add&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Otra cosa que suele hacer soltar una exclamación es que si se modifica un archivo, se hace &lt;code&gt;git add&lt;/code&gt; , se vuelve a modificar el archivo y se hace &lt;code&gt;git commit&lt;/code&gt;, los últimos cambios no estarán incluidos en commit.&lt;br&gt;
Después de cada cambio en un archivo habría que volver a hacer &lt;code&gt;git add&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;En cualquier momento se puede verificar el estado de los archivos con &lt;code&gt;git status&lt;/code&gt;, tanto antes como después del commit. &lt;br&gt;
Si eres un usuario de consola te gustará saber que es posible personalizar el prompt de la shell para saber de un vistazo si hay algo modificado o pendiente de hacer commit (para zsh hay multitud de temas, y para bash al final hay un ejemplo).&lt;/p&gt;

&lt;p&gt;Pero antes un ejemplo práctico de toda la explicación de arriba.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch master
    nothing to commit, working tree clean

&lt;span class="c"&gt;# Creo un archivo.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"TODO"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; README.md

&lt;span class="c"&gt;# Git status indicará que hay un archivo nuevo&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch master
    Untracked files:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add &amp;lt;file&amp;gt;..."&lt;/span&gt; to include &lt;span class="k"&gt;in &lt;/span&gt;what will be committed&lt;span class="o"&gt;)&lt;/span&gt;

        README.md

    nothing added to commit but untracked files present &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add"&lt;/span&gt; to track&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Si intento hacer un commit fallará, ya que README.md &lt;/span&gt;
&lt;span class="c"&gt;# esta untracked.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"creación de README.md"&lt;/span&gt;
    On branch master
    Untracked files:
        README.md

    nothing added to commit but untracked files present

&lt;span class="nv"&gt;$ &lt;/span&gt;git add README.md 

&lt;span class="c"&gt;# Tras git add README.md pasa a estar tracked y en &lt;/span&gt;
&lt;span class="c"&gt;# el area de stage.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch master
    Changes to be committed:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git reset HEAD &amp;lt;file&amp;gt;..."&lt;/span&gt; to unstage&lt;span class="o"&gt;)&lt;/span&gt;

        new file:   README.md

&lt;span class="c"&gt;# Ahora si que es posible hacer commit.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"creación de README.md"&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;master ccd62fa] creación de README.md
     1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
     create mode 100644 README.md

&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch master
    nothing to commit, working tree clean

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# Introducción"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; README.md

&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch master
    Changes not staged &lt;span class="k"&gt;for &lt;/span&gt;commit:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add &amp;lt;file&amp;gt;..."&lt;/span&gt; to update what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git checkout -- &amp;lt;file&amp;gt;..."&lt;/span&gt; to discard changes &lt;span class="k"&gt;in &lt;/span&gt;working directory&lt;span class="o"&gt;)&lt;/span&gt;

        modified:   README.md

    no changes added to commit &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add"&lt;/span&gt; and/or &lt;span class="s2"&gt;"git commit -a"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git add README.md 

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# Instalación"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; README.md

&lt;span class="c"&gt;# Los cambios de antes antes de git add están en &lt;/span&gt;
&lt;span class="c"&gt;# el area de stage; y los de después están fuera.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch master
    Changes to be committed:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git reset HEAD &amp;lt;file&amp;gt;..."&lt;/span&gt; to unstage&lt;span class="o"&gt;)&lt;/span&gt;

        modified:   README.md

    Changes not staged &lt;span class="k"&gt;for &lt;/span&gt;commit:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add &amp;lt;file&amp;gt;..."&lt;/span&gt; to update what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git checkout -- &amp;lt;file&amp;gt;..."&lt;/span&gt; to discard changes &lt;span class="k"&gt;in &lt;/span&gt;working directory&lt;span class="o"&gt;)&lt;/span&gt;

        modified:   README.md

&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"añadir secciones"&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;master f4df7c2] añadir secciones
     1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, 1 deletion&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Al haber hecho el commit sin la opción -a, solo los cambios&lt;/span&gt;
&lt;span class="c"&gt;# en el area de stage se han incluido en el commit;&lt;/span&gt;
&lt;span class="c"&gt;# si el commit se hubise hecho con -a, se habrían incluido &lt;/span&gt;
&lt;span class="c"&gt;# todos los cambios&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git status
    On branch master
    Changes not staged &lt;span class="k"&gt;for &lt;/span&gt;commit:
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add &amp;lt;file&amp;gt;..."&lt;/span&gt; to update what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git checkout -- &amp;lt;file&amp;gt;..."&lt;/span&gt; to discard changes &lt;span class="k"&gt;in &lt;/span&gt;working directory&lt;span class="o"&gt;)&lt;/span&gt;

        modified:   README.md

    no changes added to commit &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add"&lt;/span&gt; and/or &lt;span class="s2"&gt;"git commit -a"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git diff
    diff &lt;span class="nt"&gt;--git&lt;/span&gt; a/README.md b/README.md
    index 28429bb..ab9e81e 100644
    &lt;span class="nt"&gt;---&lt;/span&gt; a/README.md
    +++ b/README.md
    @@ &lt;span class="nt"&gt;-1&lt;/span&gt; +1,2 @@
     &lt;span class="c"&gt;# Introducci&amp;lt;C3&amp;gt;&amp;lt;B3&amp;gt;n&lt;/span&gt;
    +# Instalaci&amp;lt;C3&amp;gt;&amp;lt;B3&amp;gt;n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Incluyendo lo siguiente en el &lt;code&gt;~/.bashrc&lt;/code&gt;,  el prompt incluirá, cuando se esté dentro de un repositorio de Git, la rama actual y un &lt;code&gt;*&lt;/code&gt; si hay cambios pendientes de commitear&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;YELLOW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\[\0&lt;/span&gt;&lt;span class="s2"&gt;33[0;33m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;GREEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\[\0&lt;/span&gt;&lt;span class="s2"&gt;33[0;32m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;LIGHT_BLUE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\[\0&lt;/span&gt;&lt;span class="s2"&gt;33[1;34m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;WHITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\[\0&lt;/span&gt;&lt;span class="s2"&gt;33[1;37m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;COLOR_NONE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\[\e&lt;/span&gt;&lt;span class="s2"&gt;[0m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;parse_git_dirty &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git status 2&amp;gt; /dev/null | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"nothing to commit, working directory clean"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git status 2&amp;gt; /dev/null | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"nothing to commit, working tree clean"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git status 2&amp;gt; /dev/null | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"nada para hacer commit, el árbol de trabajo está limpio"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
   &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;parse_git_branch &lt;span class="o"&gt;{&lt;/span&gt;
  git branch &lt;span class="nt"&gt;--no-color&lt;/span&gt; 2&amp;gt; /dev/null | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'/^[^*]/d'&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"s/* &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="s2"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="s2"&gt;/(&lt;/span&gt;&lt;span class="se"&gt;\1&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;parse_git_dirty&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;)/"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GREEN&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="nv"&gt;$WHITE&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="nv"&gt;$YELLOW&lt;/span&gt;&lt;span class="se"&gt;\H&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$LIGHT_BLUE&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_NONE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;(parse_git_branch)&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Si has llegado hasta aquí, gracias 🙂&lt;br&gt;
Espero que te haya resultado útil, y nos vemos en el próximo post sobre ramas 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  Créditos
&lt;/h2&gt;

&lt;p&gt;Cover: &lt;a href="https://pixabay.com/es/photos/monta%C3%B1a-moj%C3%B3n-roc-cumbre-2702405/"&gt;https://pixabay.com/es/photos/monta%C3%B1a-moj%C3%B3n-roc-cumbre-2702405/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>howto</category>
      <category>commit</category>
    </item>
    <item>
      <title>Git: how to salir de esta</title>
      <dc:creator>Claudio Sánchez</dc:creator>
      <pubDate>Tue, 15 Jun 2021 12:29:23 +0000</pubDate>
      <link>https://dev.to/narkha/git-how-to-salir-de-esta-1bnd</link>
      <guid>https://dev.to/narkha/git-how-to-salir-de-esta-1bnd</guid>
      <description>&lt;p&gt;Cuando se introdujo Git en la primera empresa en lo que lo use fue más o menos así&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Git es un muy sencillo.&lt;br&gt;
"git clone" para descargarte el proyecto, "git commit -a" para hacer un commit, "git branch" para crear una rama, "git checkout" para cambiarte de rama, "git pull" para actualizar la rama y "git push" para subir los cambios al repositorio.&lt;br&gt;
Si tienes dudas mira el &lt;a href="https://github.github.com/training-kit/downloads/es_ES/github-git-cheat-sheet.pdf"&gt;cheat sheet&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Evidentemente no fue tan sencillo, y pronto empezaron a surgir los problemas ¿por qué no se ha añadido este archivo al commit? ¿qué es esto de los conflictos al actualizar la rama? ¿porque no puedo hacer push?&lt;br&gt;
Y es normal, Git es una herramienta muy potente, con muchísimas funcionalidades. Cuesta cogerle el truco, y más cuando nos lanzamos a usarlo con una introducción superficial.&lt;/p&gt;

&lt;p&gt;A lo largo de varios posts voy a contar situaciones que me he encontrado usando Git y como he aprendido a salir de ellas, ya que creo que hay multitud de artículos sobre cómo empezar con Git o sobre como hacer un flujo de trabajo, pero pocos sobre como salir del paso; y sí, está Stack Overflow, pero creo que puede ser útil agrupar algunas de las preguntas más comunes y explayarse un poco en la respuestas.&lt;/p&gt;

</description>
      <category>git</category>
      <category>howto</category>
    </item>
  </channel>
</rss>
