Git: cree una rama a partir de cambios no realizados / no confirmados en el maestro

991

Contexto: estoy trabajando en master agregando una característica simple. Después de unos minutos, me doy cuenta de que no era tan simple y que debería haber sido mejor trabajar en una nueva sucursal.

Esto siempre me sucede y no tengo idea de cómo cambiar a otra rama y llevar todos estos cambios no confirmados conmigo dejando la rama maestra limpia. Supuse git stash && git stash branch new_branchque simplemente lograría eso, pero esto es lo que obtengo:

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ echo "hello!" > testing 

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

¿Sabes si hay alguna forma de lograr esto?

knoopx
fuente
1
Aunque hay una solución más simple para su problema, ¿podría especificar en qué difiere el resultado que obtiene de lo que deseaba?
Gauthier el
2
Al hacer lo anterior o las respuestas en la parte inferior, los cambios no comprometidos se encuentran tanto en el maestro como en la nueva rama. Los quiero solo en la nueva sucursal, por lo que puedo pagar master y trabajar en otra cosa sin tener estos cambios flotando
knoopx
1
ver mi respuesta editada Debe confirmar sus cambios locales en la nueva sucursal si desea pagar un maestro limpio. Los cambios locales son solo las diferencias entre el HEAD actual y sus archivos en el disco. Estos cambios en los archivos locales no están versionados, debe decirle a git que los guarde en algún lugar si desea recuperarlos más adelante.
Gauthier

Respuestas:

1207

No hay necesidad de esconderse.

git checkout -b new_branch_name

no toca tus cambios locales. Simplemente crea la rama desde el HEAD actual y establece el HEAD allí. Así que supongo que eso es lo que quieres.

--- Editar para explicar el resultado del proceso de pago maestro ---

¿Estás confundido porque checkout master no descarta tus cambios?

Como los cambios son solo locales, git no quiere que los pierdas demasiado fácilmente. Al cambiar de rama, git no sobrescribe sus cambios locales. El resultado de tu checkout masteres:

M   testing

, lo que significa que sus archivos de trabajo no están limpios. git cambió el HEAD, pero no sobrescribió sus archivos locales. Es por eso que su último estado aún muestra sus cambios locales, aunque está enmaster .

Si realmente desea descartar los cambios locales, debe forzar el pago con -f .

git checkout master -f

Como sus cambios nunca se cometieron, los perdería.

Intente volver a su sucursal, confirme los cambios y luego vuelva a pagar el master.

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

Debería recibir un Mmensaje después del primer pago, pero luego no más después del checkout master, y no git statusdebería mostrar archivos modificados.

--- Editar para aclarar la confusión sobre el directorio de trabajo (archivos locales) ---

En respuesta a su primer comentario, los cambios locales son solo ... bueno, locales. Git no los guarda automáticamente, debe indicarle que los guarde para más adelante. Si realiza cambios y no los confirma ni los oculta explícitamente, git no los versionará. Si cambia HEAD ( checkout master), los cambios locales no se sobrescriben desde que no se guardaron.

Gauthier
fuente
32
Lo confuso aquí es que la página de manual de git dice que git checkout"Actualiza los archivos en el árbol de trabajo para que coincidan con la versión en el índice o el árbol especificado". Eso supone que sus cambios en su sistema de archivos se IDARÁN después. Sin ninguna posibilidad de recuperarlos. Incluso si dices que no lo harán, esto todavía deja un mal presentimiento. No confío en esto en absoluto . O la documentación es realmente mala o el comportamiento predeterminado de git es realmente peligroso. Uno no debería tener que confiar en alguna heurística "automática" para detectar que en este caso no desea perder sus cambios.
Evi1M4chine
16
Si está revisando una confirmación que sobrescribiría sus cambios locales (si el historial entre la confirmación actual y la confirmación de destino toca sus archivos modificados localmente), git se niega. Solo si checkoutno entra en conflicto con sus cambios locales, el pago funciona y deja los cambios locales solos. Sin embargo, entiendo el mal presentimiento, la página del manual tal vez debería decir "Actualiza archivos no modificados en el árbol de trabajo". Git, por otro lado, no hace que sea demasiado fácil perder los cambios locales. git checkouto deja solo los cambios locales o se niega si hay un conflicto.
Gauthier
1
bueno, ¿cómo pagaría en otra sucursal sin traer los cambios locales allí?
ア レ ッ ク ス
55
@Alex git checkout <other_branch> -f. Perderá sus cambios locales sin previo aviso.
Gauthier
2
@ Evi1M4chine El primero. La documentación es realmente mala.
Qwertie
62

Tratar:

git stash
git checkout -b new-branch
git stash apply
Grant Limberg
fuente
66
¿Es esto diferente a solo hacer 'git checkout -b new-branch' por sí mismo?
Adrian Mouat
No creo que fuera cuando la respuesta se escribió originalmente, pero podría estar equivocado. Desafortunadamente debido a mi circunstancia laboral, he estado usando forzosamente durante los últimos años, así que no puedo dar fe de su precisión ahora.
Grant Limberg
66
O en lugar de los dos últimos pasos: git stash branch new-branch
rethab
1
git stash ya no es necesario
kory
Cuando tienes una rama ya existente donde quieres poner todas tus cosas, el escondite tiene sentido para mí: (Eventualmente git fetch --todos; para obtener la rama remota en el origen) git stash; git checkout <rama existente>; git stash se aplica;
Paolof76
24

Dos cosas que puedes hacer:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

o

git stash -u
git branch sillyname stash@{0}

(git checkout - <- el guión es un acceso directo para la rama anterior en la que estaba)

( git stash -u<- -usignifica que también se necesitan cambios no organizados)

Pylinux
fuente
7

Si está utilizando el cliente de Windows GitHub (como yo) y se encuentra en la situación de haber realizado cambios no comprometidos que desea mover a una nueva sucursal, simplemente puede "crear una nueva sucursal" a través del cliente GitHub. Cambiará a la rama recién creada y preservará sus cambios.

ingrese la descripción de la imagen aquí

Tod Birdsall
fuente
que oculta los cambios antes de crear la nueva rama para que no los conserve (versión 223 en Mac OS)
Fernando Gallego
2

Si desea que sus cambios actuales no confirmados en la rama actual se muevan a una nueva rama, use el siguiente comando para crear una nueva rama y copiar los cambios no confirmados automáticamente.

git checkout -b branch_name

Esto creará una nueva rama de su rama actual (suponiendo que sea maestra), copie los cambios no confirmados y cambie a la nueva rama.

Confirma tus cambios en la nueva sucursal.

git commit -m "First commit"

Como se crea una nueva rama, antes de llevarla a control remoto, debe configurarla en sentido ascendente. Use el siguiente comando para configurar el flujo ascendente y empujarlo a remoto.

git push --set-upstream origin feature/feature/NEWBRANCH

Una vez que presione este comando, se creará una nueva rama en el control remoto y su nueva rama local se enviará a control remoto.

Ahora, si desea descartar sus cambios no confirmados de la rama maestra, use:

git checkout master -f

Esto eliminará cualquier cambio local no confirmado al finalizar la compra.

Disidente
fuente
¿Cómo difiere esta respuesta de la respuesta aceptada?
Kometen
Aunque existe cierta superposición con la respuesta aceptada, esto proporciona una guía paso a paso simple, y también incluye las operaciones necesarias para impulsar una nueva sucursal de forma remota. Simple, claro y útil.
Kjartan
Esta respuesta es clara y me ayudó mucho.
Vadim
0

En el último cliente de GitHub para Windows , si tiene cambios no confirmados y elige crear una nueva sucursal.
Le indica cómo manejar este escenario exacto:

ingrese la descripción de la imagen aquí

Lo mismo se aplica si simplemente cambia la rama también.

Jerry Dodge
fuente