Pregunta rama principal y 'origen / maestro' han divergido, ¿cómo 'desviar' ramas '?


De alguna manera, mi maestro y mi rama de origen / maestro han divergido. De hecho, no quiero que se separen. ¿Cómo puedo ver estas diferencias y 'fusionarlas'?


723
2018-03-16 05:05


origen


Respuestas:


Usted puede revise las diferencias con un:

git log HEAD..origin/master

antes de tirando de él (buscar + fusionar) (ver también "¿Cómo haces para que Git siempre saque algo de una rama específica?")


Cuando tienes un mensaje como:

"Su rama y 'origen / maestro' han divergido, # y tienen 1 y 1 compromiso (s) diferente cada uno, respectivamente."

, comprueba si necesita actualizar origin. Si origin está actualizado, entonces algunos commits han sido empujados a origin de otro repositorio mientras realizaba sus propios compromisos localmente.

... o ---- o ---- A ---- B  origin/master (upstream work)
                   \
                    C  master (your work)

Tu cometiste la confirmación C en la confirmación A porque ese era el último trabajo que habías obtenido de la corriente ascendente en ese momento.

Sin embargo, antes de intentar empujar hacia atrás al origen, alguien más empujó el compromiso B.
El historial de desarrollo se ha dividido en caminos separados.

A continuación, puede combinar o rebase. Ver Pro Git: Git Branching - Rebasing para detalles.

Unir

Use el comando git merge:

$ git merge origin/master

Esto le dice a Git que integre los cambios de origin/master en tu trabajo y crea un commit de fusión.
El gráfico de la historia ahora se ve así:

... o ---- o ---- A ---- B  origin/master (upstream work)
                   \      \
                    C ---- M  master (your work)

La nueva combinación, commit M, tiene dos padres, cada uno representa una ruta de desarrollo que condujo al contenido almacenado en esa confirmación.

Tenga en cuenta que el historial detrás de M ahora no es lineal.

Rebase

Use el comando git rebase:

$ git rebase origin/master

Esto le dice a Git que reproduzca el compromiso C (su trabajo) como si lo hubiera basado en el compromiso B en lugar de A.
Los usuarios de CVS y Subversion ajustan de forma rutinaria sus cambios locales sobre el trabajo de subida cuando se actualizan antes de la confirmación.
Git simplemente agrega una separación explícita entre los pasos commit y rebase.

El gráfico de la historia ahora se ve así:

... o ---- o ---- A ---- B  origin/master (upstream work)
                          \
                           C'  master (your work)

Commit C 'es un nuevo commit creado por el comando git rebase.
Es diferente de C de dos maneras:

  1. Tiene una historia diferente: B en lugar de A.
  2. Su contenido explica los cambios en B y C; es lo mismo que M del ejemplo de combinación.

Tenga en cuenta que la historia detrás de C 'sigue siendo lineal.
Hemos elegido (por ahora) permitir solo la historia lineal en cmake.org/cmake.git.
Este enfoque conserva el flujo de trabajo basado en CVS utilizado anteriormente y puede facilitar la transición.
Un intento de presionar C 'en nuestro repositorio funcionará (suponiendo que tenga permisos y nadie lo haya empujado mientras estaba reajustando).

El comando git pull proporciona una forma abreviada de recuperar datos del origen y volver a trabajar localmente en él:

$ git pull --rebase

Esto combina los pasos de recuperación y rebase anteriores en un solo comando.


812
2018-03-16 07:02



Tuve esto y estoy desconcertado en cuanto a lo que lo ha causado, incluso después de leer las respuestas anteriores. Mi solución fue hacer

git reset --hard origin/master

Luego, eso solo restablece mi copia (local) del maestro (que supongo que está estropeada) en el punto correcto, como se representa por el origen / maestro (remoto).

ADVERTENCIA: Perderá todos los cambios que aún no se hayan enviado a origin/master.


483
2017-12-12 14:40



git pull --rebase origin/master 

es un solo comando que puede ayudarte la mayor parte del tiempo.

Editar: Extrae las confirmaciones del origen / maestro y aplica sus cambios sobre el nuevo historial de sucursal extraída.


37
2018-03-21 04:10



Me encontré en esta situación cuando traté de rebase una rama que estaba rastreando una rama remota, y yo estaba tratando de volver a establecer la base en el maestro. En este escenario, si intenta volver a establecer la base, lo más probable es que encuentre su sucursal divergido y puede crear un desastre que no es para git nubees!

Digamos que estás en la rama my_remote_tracking_branch, que se ramificó desde el maestro

$ git status

# En la rama my_remote_tracking_branch

nada que comprometer (directorio de trabajo limpio)

Y ahora estás tratando de rebase desde el maestro como:

git rebase master

¡PARE AHORA y ahórrese algunos problemas! En su lugar, use fusionar como:

git merge master

Sí, terminará con compromisos adicionales en su sucursal. Pero a menos que esté listo para las ramas "no divergentes", este será un flujo de trabajo mucho más suave que el rebase. Ver este blog para una explicación mucho más detallada.

Por otro lado, si su sucursal es solo una local sucursal (es decir, aún no se ha enviado a ningún control remoto) definitivamente debe hacer una rebase (y su sucursal no divergir en este caso).

Ahora si estás leyendo esto porque ya estás son en un escenario "divergente" debido a dicha rebase, puede volver al último compromiso desde el origen (es decir, en un estado no divergente) utilizando:

git reset --hard origin / my_remote_tracking_branch


22
2018-05-18 09:21



En mi caso, aquí está lo que hice para causar la divergido mensaje: lo hice git push pero luego lo hizo git commit --amend para agregar algo al mensaje de compromiso. Luego también hice otro compromiso.

Entonces, en mi caso, eso simplemente significaba que Origin / Master estaba desactualizado. Como sabía que nadie más tocaba el origen / maestro, la solución era trivial: git push -f  (dónde -f significa fuerza)


18
2018-01-23 03:03



En mi caso, he impulsado cambios en origin/master y luego me di cuenta de que no debería haberlo hecho así :-( Esto se complicó por el hecho de que los cambios locales estaban en un subárbol. Así que volví al último compromiso bueno antes de los cambios locales "malos" (usando Source Tree) y luego obtuve el "mensaje de divergencia".

Después de arreglar mi desastre localmente (los detalles no son importantes aquí) quise "retroceder en el tiempo" el control remoto origin/master rama para que esté sincronizado con el local master de nuevo. La solución en mi caso fue:

git push origin master -f

Nota la -f (fuerza) cambiar. Esto eliminó los "malos cambios" que se habían llevado a cabo origin/master por error y ahora las sucursales locales y remotas están sincronizadas.

Tenga en cuenta que esta es una operación potencialmente destructiva, realice solo si está 100% seguro de que "mover hacia atrás" el control remoto a tiempo es correcto.


5
2018-06-27 08:58



En mi caso, esto fue causado por no comprometer mi resolución de conflicto.

El problema fue causado al ejecutar el git pullmando. Los cambios en el origen provocaron conflictos con mi repositorio local, que resolví. Sin embargo, no los cometí. La solución en este punto es comprometer los cambios (git commit el archivo resuelto)

Si también ha modificado algunos archivos desde la resolución del conflicto, el git status comando mostrará las modificaciones locales como modificaciones locales sin escenario y resolución de fusión como modificaciones locales por etapas. Esto se puede resolver de manera adecuada al realizar cambios desde la combinación primero por git commit, luego agregue y confirme los cambios no registrados como de costumbre (por ejemplo, git commit -a)


3
2018-02-25 08:47



Para ver las diferencias:

git difftool --dir-diff master origin/master

Esto mostrará los cambios o diferencias entre las dos ramas. En araxis (Mi favorito) lo muestra en un estilo de diff de carpeta. Mostrando cada uno de los archivos modificados. Luego puedo hacer clic en un archivo para ver los detalles de los cambios en el archivo.


3
2018-04-28 17:42



Sé que hay muchas respuestas aquí, pero creo git reset --soft HEAD~1 merece algo de atención, porque te permite mantener los cambios en el último local (no empujado) cometer mientras se resuelve el estado divergente. Creo que esta es una solución más versátil que tirar con rebase, porque el compromiso local se puede revisar e incluso mover a otra sucursal.

La clave es usar --soft, en lugar de los duros --hard. Si hay más de 1 confirmación, una variación de HEAD~x Deberia trabajar. Aquí están todos los pasos que resolvieron mi situación (tuve 1 confirmación local y 8 confirmaciones en el control remoto):

1)  git reset --soft HEAD~1 para deshacer la confirmación local. Para los siguientes pasos, he usado la interfaz en SourceTree, pero creo que los siguientes comandos también deberían funcionar:

2)  git stash para ocultar los cambios de 1). Ahora todos los cambios son seguros y ya no hay divergencia.

3)  git pull para obtener los cambios remotos

4)  git stash pop o git stash apply para aplicar los últimos cambios escondidos, seguido de un nuevo compromiso, si así lo desea. Este paso es opcional, junto con 2), cuando desee eliminar los cambios en la confirmación local. Además, cuando desee comprometerse con otra sucursal, este paso debe realizarse después de cambiar a la deseada.


3
2017-09-22 13:54