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''yE''contienen los mismos cambios queDyEpero tienen diferentes ID de confirmación porque se han vuelto a basar sobreF
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:
- Mover
featurepara confirmarC(el antecesor común defeatureyorigin/feature) - Aplicar
DyEdesdeorigin/feature - Aplicar
F,D''yE''
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'' .