tutorial stackoverflow explicado git rebase

stackoverflow - git pull*after*git rebase?



git rebase tutorial (4)

Cuando rebasó su rama de características en la parte superior del maestro, creó un montón de nuevas confirmaciones. Sin embargo, su rama de origin/feature sigue apuntando a las antiguas. Esta es la situación después de la rebase:

C'' (feature) B'' A'' * (master, origin/master) * * | C (origin/feature) | B | A |/ * some base commit

Mientras que la confirmación A'' contiene un conjunto de cambios similar a la confirmación A , de ninguna manera es la misma confirmación. Contiene un árbol diferente, y tiene un padre diferente.

Ahora, cuando intenta volver a activar la feature , intenta crear este historial:

* (feature) |/ C''| B''| A''| * | (master, origin/master) * | * | | C (origin/feature) | B | A |/ * some base commit

Usted está fusionando dos ramas que han introducido cambios muy similares a chorros. Esto está destinado a crear una tonelada de conflictos, además de ser totalmente inútil.

Lo que debe hacer es informar a su representante de flujo ascendente acerca de la rebase utilizando git push -f . Esto perderá la historia antigua, y la reemplazará con la reescrita .

La alternativa es evitar el uso de git rebase en las sucursales que ya haya git rebase a cualquier otro repositorio, o evitar el git rebase completo. Este es el enfoque más limpio : resulta en la historia tal como sucedió, en lugar de decir mentiras sobre la historia como lo hace git rebase . Eso es al menos lo que prefiero.

Tengo una rama característica, y una rama maestra.

La rama maestra ha evolucionado y me refiero a hacer que esas actualizaciones se aparten lo menos posible de la rama maestra.

Así que git pull en ambas ramas, git checkout feature/branch y finalmente git rebase master .

Ahora, o bien aquí espero que todo funcione correctamente o que aparezcan conflictos que debo resolver antes de continuar con la rebase hasta que todas las confirmaciones maestras se vuelvan a aplicar con éxito en la rama de características.

Ahora, lo que realmente sucedió en mi caso es algo que no entiendo:

$>git rebase master First, rewinding head to replay your work on top of it... Applying: myFirstCommitDoneOnTheBranch Applying: myOtherCommitDoneOnTheBranch $>git status On branch feature/branch Your branch and ''origin/feature/feature'' have diverged, and have 27 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) nothing to commit, working tree clean $>git pull *load of conflicts*

Ahora, por mucho que pueda entender, está cargada de conflictos después del tirón; No entiendo la necesidad de un tirón. Lógicamente, debería volver al maestro cuando se ramificó, guardar los compromisos realizados en la rama, reenviarlos al último compromiso en el maestro y luego aplicar los compromisos guardados.

No entiendo a qué se refiere el mensaje de Applying : ¿qué es la aplicación de las confirmaciones en qué versión?


Si las versiones remotas de master y feature/branch están actualizadas individualmente, simplemente reinicie su rama de características local

git checkout feature/branch git fetch origin feature/branch git reset --hard origin/feature/branch

entonces si quieres introducir cambios en la rama master ,

git rebase origin/master


have 27 and 2 different commits each que le origin/<yourbranch> que ahora tiene 27 confirmaciones nuevas del master y 2 confirmaciones nuevas en su sucursal que no están presentes en el origin/<yourbranch> .

Debido a que el origin/<yourbranch> ha sido modificado masivamente por la rebase, ya no tiene una base común con origin/<yourbranch> . Por lo tanto, no desea extraer los cambios desde el origin/<yourbranch> después de la rebase, porque, como ve, todo H *** se suelta.

Si sabe que hay cambios en el origin/<yourbranch> que necesita en su sucursal local, tire de ellos antes de volver a armar.

Si está seguro de que nadie ha cambiado de origin/<yourbranch> desde su último impulso (una apuesta segura si esta es su propia rama de características), puede usar push --force para sincronizarlos nuevamente. Luego, origin/<yourbranch> nuevamente tendrá la misma base que su sucursal local y esa base contendrá todos los últimos cambios master .


tl; dr Debes actualizar el master y la feature con git pull y git pull --rebase antes de git pull --rebase feature en la parte superior del master . No hay necesidad de hacer un git pull después de que haya rebasado su rama de feature en la parte superior del master .

Con tu flujo de trabajo actual, la razón por la que el git status está diciendo esto:

Su rama y ''origen / característica'' se han desviado, y tienen 27 y 2 confirmaciones diferentes cada una, respectivamente.

Esto se debe a que su rama de feature rebasada ahora tiene 25 confirmaciones nuevas que no son accesibles desde el origin/feature (ya que provienen de la base en el master ) más 2 confirmaciones que son accesibles desde el origin/feature pero tienen diferentes ID de confirmación. Esos compromisos contienen los mismos cambios (es decir, son parches equivalentes ) pero tienen diferentes hashes SHA-1 porque se basan en un origin/feature diferente del que los ha cambiado en su repositorio local.

Aquí hay un ejemplo. Supongamos que esta es tu historia antes de hacer git pull en master :

A - B - C (master) / D - E (feature)

Después de git pull , el master consiguió cometer F :

A - B - C - F (master, origin/master) / D - E (feature)

En ese punto, se vuelve a generar la feature en la parte superior del master , que aplica D y E :

A - B - C - F (master, origin/master) / D - E (feature)

Mientras tanto, el origin/feature rama remota aún se basa en la confirmación C :

A - B - C - F (master, origin/master) / / / D'' - E'' (feature) / D - E (origin/feature)

Si realiza un git status en la feature , Git le dirá que su rama de la feature se ha desviado del origin/feature con 3 ( F , D'' , E'' ) y 2 ( D , E ) confirmaciones, respectivamente.

Tenga en cuenta que D'' y E'' contienen los mismos cambios que D y E pero tienen diferentes ID de confirmación porque se han vuelto a basar sobre F

La solución es hacer git pull en el master y la feature antes de rebasar la feature en el master . Sin embargo, como es posible que tenga confirmaciones en la feature que aún no ha introducido en el origin , desearía hacerlo:

git checkout feature && git pull --rebase

para evitar crear una confirmación de fusión entre origin/feature y su feature local.

Actualización sobre las consecuencias de rebasar:

A la luz de este comentario , amplié las ramas divergentes. La razón por la que git status informa que la feature y el origin/feature divergen después de la reorganización se debe al hecho de que el reabastecimiento trae nuevos compromisos a la feature , además de que reescribe los confirmaciones que se enviaron previamente al origin/feature .

Considere la situación después del tirón pero antes de la rebase:

A - B - C - F (master) / D - E (feature, origin/feature)

En este punto, la feature y el origin/feature apuntan a la misma confirmación E en otras palabras, están en " sincronización ". Después de rebasar la feature en la parte superior del master , el historial se verá así:

A - B - C - F (master) / / / D'' - E'' (feature) / D - E (origin/feature)

Como puede ver, la feature y el origin/feature han divergido , su ancestro común está comprometido con C Esto se debe a que la feature ahora contiene la nueva confirmación F del master más D'' y E'' (leída como " D prime " y " E prime "), que son las confirmaciones D y E aplicadas sobre F A pesar de que contienen los mismos cambios, Git los considera diferentes porque tienen diferentes ID de confirmación. Mientras tanto, el origin/feature aún hace referencia a D y E

En este punto, ha reescrito la historia : ha modificado las confirmaciones existentes en virtud de volver a basarlas, creando efectivamente "nuevas".

Ahora, si tuviera que ejecutar la función git pull on esto es lo que sucedería:

A - B - C - F (master) / / / D'' - E''- M (feature) / / D - E - (origin/feature)

Dado que git pull hace git fetch + git merge , esto resultaría en la creación del merge commit M , cuyos padres son E'' y E

Si, en cambio, ejecutó git pull --rebase (es decir, git fetch + git rebase ), entonces Git:

  1. Mover feature para confirmar C (el antecesor común de feature y origin/feature )
  2. Aplicar D y E desde origin/feature
  3. Aplicar F , D'' y E''

Sin embargo, al darse cuenta de que D'' y E'' contienen los mismos cambios que D y E , Git simplemente los descartaría, lo que resultaría en una historia como esta:

A - B - C - F (master) / D - E - F'' (feature) ^ (origin/feature)

Observe cómo el commit F , que antes era accesible desde la feature , se aplicó en la parte superior del origin/feature resultó en F'' . En este punto, el git status te diría esto:

Su sucursal está por delante de ''origen / característica'' por 1 confirmación.

Que se comprometan siendo, por supuesto, F'' .