De alguna manera mi maestro y mi rama de origen / maestro han divergido.
En realidad no quiero que diverjan.
¿Cómo puedo ver estas diferencias y 'fusionarlas'?
De alguna manera mi maestro y mi rama de origen / maestro han divergido.
En realidad no quiero que diverjan.
¿Cómo puedo ver estas diferencias y 'fusionarlas'?
Respuestas:
Puede revisar las diferencias con un:
git log HEAD..origin/master
antes de extraerlo (buscar + fusionar) (consulte también "¿Cómo se consigue que git siempre extraiga de una rama específica?" )
Cuando tienes un mensaje como:
"Su rama y 'origin / master' han divergido, # y tienen 1 y 1 commit (s) diferentes cada uno, respectivamente".
, verifique si necesita actualizarorigin
. Si origin
está actualizado, se han enviado algunas confirmaciones origin
desde otro repositorio mientras usted realizaba sus propias confirmaciones localmente.
... o ---- o ---- A ---- B origin/master (upstream work)
\
C master (your work)
Usted basó el compromiso C en el compromiso A porque ese era el último trabajo que había obtenido de la cadena ascendente en ese momento.
Sin embargo, antes de intentar regresar al origen, otra persona presionó la confirmación B.
El historial de desarrollo ha divergido en caminos separados.
Luego puede fusionar o rebase. Ver Pro Git: Git Branching - Rebasing para más detalles.
Unir
Use el comando git merge:
$ git merge origin/master
Esto le dice a Git que integre los cambios origin/master
en su trabajo y cree una confirmación 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 representando una ruta de desarrollo que condujo al contenido almacenado en ese commit.
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 vuelven a redactar sus cambios locales en la parte superior del trabajo ascendente cuando se actualizan antes de confirmar.
Git solo 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:
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 insertar C 'en nuestro repositorio funcionará (suponiendo que tenga permisos y que nadie haya presionado mientras estaba haciendo un rebase).
El comando git pull proporciona una forma abreviada de buscar desde el origen y modificar el trabajo local en él:
$ git pull --rebase
Esto combina los pasos de recuperación y rebase anteriores en un solo comando.
git reset --hard HEAD
solo eliminaría cualquier modificación no comprometida indexada local y no haría nada para conciliar las diferencias entre las confirmaciones locales y remotas . Solo una fusión o un rebase reunirán los dos conjuntos de confirmaciones (la local y la remota).
master
señalar B
su ejemplo.
git reset --hard origin/master
como se menciona en la respuesta a continuación: stackoverflow.com/a/8476004/6309
Tenía esto y estoy desconcertado sobre lo que lo causó, 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á jodida) en el punto correcto, como se representa por el origen / maestro (remoto).
ADVERTENCIA : perderá todos los cambios que aún no se hayan presionado
origin/master
.
git reflog
ellos o verlos gitk --all
. Pero, sin embargo, por supuesto, el restablecimiento completo es algo más que un rebase.
git pull --rebase origin/master
es un comando único que puede ayudarlo la mayor parte del tiempo.
Editar: Extrae las confirmaciones del origen / maestro y aplica sus cambios al historial de rama recién extraído.
Me encontré en esta situación cuando intenté cambiar la base de una rama que estaba rastreando una rama remota, y estaba tratando de cambiar la base en master. En este escenario, si intentas cambiar la base, lo más probable es que encuentres tu rama divergente y puede crear un desastre que no es para git nubees.
Digamos que está en la rama my_remote_tracking_branch, que fue ramificada desde master
$ git status
# En la rama my_remote_tracking_branch
nada que comprometer (directorio de trabajo limpio)
Y ahora estás tratando de rebase del maestro como:
git rebase master
¡DETÉNGASE AHORA y ahorrese algunos problemas! En su lugar, use merge como:
git merge master
Sí, terminarás con compromisos adicionales en tu rama. Pero a menos que esté preparado para ramas "no divergentes", este será un flujo de trabajo mucho más fluido que el rebase. Vea este blog para una explicación mucho más detallada.
Por otro lado, si su sucursal es solo una sucursal local (es decir, aún no se ha enviado a ningún control remoto), definitivamente debe hacer un rebase (y su sucursal no divergerá en este caso).
Ahora, si está leyendo esto porque ya se encuentra en un escenario "divergente" debido a dicho rebase, puede volver al último commit desde el origen (es decir, en un estado no divergente) usando:
git reset --hard origin / my_remote_tracking_branch
rebase
si la rama que está cambiando no ha sido publicada (y utilizada por otras personas). De lo contrario, use merge
. Si modifica las ramas ya publicadas (y usadas), debe coordinar una conspiración para reescribir el historial en cada desarrollador que haya usado su rama.
git rebase master
...
git reset --hard origin/my_remote_tracking_branch
es lo que realmente funcionó
En mi caso, esto es lo que hice para causar el mensaje divergente : lo hice git push
pero luego lo hice git commit --amend
para agregar algo al mensaje de confirmación. Luego también hice otra confirmación.
Entonces, en mi caso, eso simplemente significaba que origen / maestro estaba desactualizado. Como sabía que nadie más estaba tocando origen / maestro, la solución fue trivial: git push -f
(donde -f
significa fuerza)
git push -f
sobrescribir los cambios previamente confirmados y enviados al origen. También estoy seguro de que nadie más tocó el repositorio.
En mi caso, impulsé los cambios origin/master
y luego me di cuenta de que no debería haberlo hecho :-( Esto fue complicado por el hecho de que los cambios locales estaban en un subárbol. Así que volví al último buen commit antes del "malo" local cambios (usando SourceTree) y luego recibí el "mensaje de divergencia".
Después de arreglar mi desorden localmente (los detalles no son importantes aquí) quería "retroceder en el tiempo" la origin/master
rama remota para que estuviera sincronizada con el local master
nuevamente. La solución en mi caso fue:
git push origin master -f
Tenga en cuenta el -f
interruptor (fuerza). Esto eliminó los "cambios incorrectos" que se habían introducido origin/master
por error y ahora las ramas locales y remotas están sincronizadas.
Tenga en cuenta que esta es una operación potencialmente destructiva, así que realicela solo si está 100% seguro de que "retroceder" el maestro remoto a tiempo está bien.
You are not allowed to force push code to a protected branch on this project.
. Estoy tratando de empujar a mi tenedor.
Sé que hay muchas respuestas aquí, pero creo que git reset --soft HEAD~1
merece algo de atención, porque le permite mantener los cambios en el último compromiso local (no presionado) mientras resuelve el estado divergente. Creo que esta es una solución más versátil que pull rebase
, ya que el commit local puede revisarse e incluso trasladarse a otra sucursal.
La clave está usando --soft
, en lugar de la dura --hard
. Si hay más de 1 commit, una variación de HEAD~x
debería funcionar. Así que aquí están todos los pasos que resolvieron mi situación (tenía 1 confirmación local y 8 confirmaciones en el control remoto):
1) git reset --soft HEAD~1
deshacer el compromiso 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 guardar 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, seguidos de una nueva confirmación, si así lo desea. Este paso es opcional, junto con 2) , cuando se desea eliminar los cambios en la confirmación local. Además, cuando desee comprometerse con otra rama, este paso debe hacerse después de cambiar a la deseada.
pull --rebase
escondite automáticamente de todos modos. stackoverflow.com/a/30209750/6309
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 carpeta diff. Mostrando cada uno de los archivos modificados. Luego puedo hacer clic en un archivo para ver los detalles de los cambios en el archivo.
En mi caso, esto fue causado por no comprometer mi resolución de conflictos.
El problema fue causado al ejecutar el git pull
comando. Los cambios en el origen llevaron a conflictos con mi repositorio local, que resolví. Sin embargo, no los cometí. La solución en este punto es confirmar los cambios ( git commit
el archivo resuelto)
Si también ha modificado algunos archivos desde que resolvió el conflicto, el git status
comando mostrará las modificaciones locales como modificaciones locales no preparadas y combinará la resolución como modificaciones locales preparadas. Esto se puede resolver adecuadamente al confirmar los cambios de la fusión primero git commit
, luego agregando y confirmando los cambios no organizados como de costumbre (por ejemplo, por git commit -a
).
Tenía el mismo mensaje cuando intentaba editar el último mensaje de confirmación, de confirmación ya empujada, usando: git commit --amend -m "New message"
Cuando presioné los cambios usando git push --force-with-lease repo_name branch_name
no hubo problemas.
Encontré este problema cuando creé una rama basada en la rama A por
git checkout -b a
y luego configuro el flujo ascendente de la rama a la rama de origen B por
git branch -u origin/B
Entonces recibí el mensaje de error anterior.
Una forma de resolver este problema para mí fue,
git checkout -b b origin/B