¿Cómo fusiono mis cambios locales no confirmados en otra rama de Git?

621

¿Cómo puedo hacer lo siguiente en Git?

Mi sucursal actual es branch1 y he realizado algunos cambios locales. Sin embargo, ahora me doy cuenta de que realmente tenía la intención de aplicar estos cambios a branch2. ¿Hay alguna forma de aplicar / fusionar estos cambios para que se conviertan en cambios locales en branch2 sin comprometerlos en branch1?

Solsberg
fuente
2
Hay un gran tutorial de Git aquí en SO. Es una especie de central para todas las preguntas de git sobre desbordamiento de pila.
Decio Lira

Respuestas:

898

Dado que sus archivos aún no se han confirmado en branch1 :

git stash
git checkout branch2
git stash pop

o

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Como se ha comentado por benjohn (ver git stashpágina del manual ):

Para guardar también los archivos no rastreados actualmente (recién agregados), agregue el argumento -u, entonces:

git stash -u
VonC
fuente
2
De nada. Más ejemplos de uso de alijo en unethicalblogger.com/posts/2008/11/… .
VonC
2
Si está buscando una solución para el mismo problema pero con TFS, la solución equivalente es archivar sus cambios y luego usar TFS Power Tools para desplazarse a la rama correcta utilizando el modificador / migrate.
xr280xr
1
Esto funcionó para mí. Sin embargo, también tuve que crear una rama local para que funcione el 'stash pop'. Echa un vistazo a stackoverflow.com/questions/1783405/git-checkout-remote-branch si algo similar te está sucediendo.
mimoralea
21
También para guardar archivos actualmente sin seguimiento (recién añadidos) , añada el argumento -u, por lo que: git stash -u.
Benjohn
2
@Benjohn Buen punto. He incluido tu comentario en la respuesta para mayor visibilidad.
VonC
84

El ocultamiento, los compromisos temporales y el rebase pueden ser excesivos. Si aún no ha agregado los archivos modificados al índice, entonces puede simplemente retirar la otra rama.

git checkout branch2

Esto funcionará siempre que ningún archivo que esté editando sea diferente entre branch1 y branch2. Te dejará en branch2 con tus cambios de trabajo preservados. Si son diferentes, puede especificar que desea fusionar sus cambios locales con los cambios introducidos al cambiar de sucursal con la -mopción de pagar.

git checkout -m branch2

Si ha agregado cambios al índice, primero querrá deshacer estos cambios con un reinicio. (Esto preservará su copia de trabajo, solo eliminará los cambios organizados).

git reset
CB Bailey
fuente
3
Pensé que el escondite era "más simple" de alguna manera de entender, pero su enfoque es mejor al tener en cuenta el directorio de trabajo en las diferentes ramas. +1
VonC
66
Un proceso de pago tradicional simple parecía más apropiado para el problema en cuestión. el pago es más liviano, solo actualiza los archivos que necesitan cambiar. Tal vez sea más fácil entender el enfoque oculto, o puede ser que no sea lo suficientemente obvio que el pago sea 'seguro' en este caso de uso.
CB Bailey
Si checkout -mno es "seguro" en alguna situación (tal vez causaría un conflicto de fusión), ¿el escondite proporcionaría alguna ventaja (por ejemplo, ¿puedes abrir un pop oculto?)
Craig McQueen
1
@craigMcQueen No puedes abrir un alijo reventado, pero el alijo se quejaría de conflictos cuando lo reventas. Puede solucionar los conflictos y luego confirmar, pero el alijo original todavía está en la pila en este caso. :)
Shaun F
En el caso de un conflicto de fusión, ¿no se realiza una copia de seguridad de los archivos .orig?
jocull
13

Una alternativa más corta al enfoque de escondite mencionado anteriormente sería:

Mueve temporalmente los cambios a un alijo.

  1. git stash

Cree y cambie a una nueva rama y luego haga estallar el alijo en solo un paso.

  1. git stash branch new_branch_name

Luego justo addy commitlos cambios a esta nueva rama.

rbento
fuente
10

ADVERTENCIA: No para git novatos.

Esto surge lo suficiente en mi flujo de trabajo que casi he intentado escribir un nuevo comando git para él. El git stashflujo habitual es el camino a seguir, pero es un poco incómodo. Por lo general, primero hago una nueva confirmación ya que si he estado mirando los cambios, toda la información está fresca en mi mente y es mejor simplemente comenzar a git commitencontrar lo que encontré (generalmente una corrección de error perteneciente al maestro que descubro mientras trabajo en un función de rama) de inmediato.

También es útil, si se encuentra mucho en situaciones como esta, tener otro directorio de trabajo junto al actual que siempre tenga la masterrama desprotegida.

Entonces, cómo logro esto es así:

  1. git commit los cambios de inmediato con un buen mensaje de compromiso.
  2. git reset HEAD~1 para deshacer la confirmación de la rama actual.
  3. (opcional) continuar trabajando en la función.

A veces más tarde (asincrónicamente), o inmediatamente en otra ventana de terminal:

  1. cd my-project-master que es otro WD que comparte lo mismo .git
  2. git reflog para encontrar la corrección de errores que acabo de hacer.
  3. git cherry-pick SHA1 del compromiso.

Opcionalmente (aún asíncrono), puede volver a crear una base de datos (o combinar) para obtener la corrección de errores, generalmente cuando está a punto de enviar un RP y ya ha limpiado su rama de características y WD:

  1. cd my-project cual es el WD principal en el que estoy trabajando.
  2. git rebase master para obtener las correcciones de errores.

De esta manera, puedo seguir trabajando en la función sin interrupciones y no tener que preocuparme de hacer git stashnada o tener que limpiar mi WD antes de un git checkout(y luego hacer que la verificación de la ramificación de la función vuelva a salir.) Y todavía tengo todas mis correcciones de errores en masterlugar de escondido en mi rama característica.

OMI git stashy git checkoutes un verdadero PIA cuando estás trabajando en una gran característica.

chakrit
fuente
Alternativa interesante y válida a mi respuesta. +1
VonC
¿Vienes de mercurial? El my-project-masterintercambio de los mismos .githace que suene como él. ¿Por qué no git checkout -b bugfixABC; git commit -a; git reset HEAD^ --hard, entonces más tarde (asíncrona), mientras que en master, git cherry-pick <SHA1 of the commit(s) in bugfixABC? (o incluso, para no tener que averiguar el SHA1, git rebase --onto master feature bugfixABC, de donde la rama se encuentra actualmente en lo que significa que puede hacerlo directamente después de la. git resetanterior, mientras que en feature.)
Gauthier
Sin embargo, OP parece que no están listos para confirmar los cambios, en ese caso checkout -mes mejor.
Gauthier
2

Si se tratara de cambios comprometidos, debería echar un vistazo a git-rebase, pero como lo señala VonC en un comentario, ya que está hablando de cambios locales, git-stash ciertamente sería la buena manera de hacerlo.

claf
fuente
No entiendo esta solución: reescribiría el historial de confirmación de branch2 de branch1 ... ¿por qué obtener todos los cambios confirmados de branch1 en branch2 cuando solo queremos obtener cambios locales no comprometidos de branch1 en branch2? ...
VonC
@VonC: acordado, en este caso, el rebase obtiene todos los cambios comprometidos desde la última fusión entre sucursales en branch1. Al principio no obtuve el parámetro "no comprometido" de esta pregunta. rebase no es la buena respuesta.
claf
@claferri: pfew ... Estaba empezando a tener dolor de cabeza;) Hubiera rechazado su respuesta, pero como yo mismo había publicado una, había un "claro conflicto de intereses". Con su publicación actualizada, no tengo que votar en absoluto ahora. Gracias :)
VonC
@VonC: la próxima vez, siéntase libre de rechazar el voto siempre que mi respuesta sea tan incorrecta como esta;)
claf
1

Las respuestas dadas hasta ahora no son ideales porque requieren mucho trabajo innecesario para resolver conflictos de fusión, o hacen suposiciones que frecuentemente son falsas. Así es como se hace perfectamente. El enlace es a mi propio sitio.

Cómo comprometerse con una rama diferente en git

Tiene cambios no confirmados en los my_branchque desea comprometerse master, sin comprometer todos los cambios demy_branch .

Ejemplo

git merge master
git stash -u
git checkout master
git stash apply
git reset
git add example.js
git commit
git checkout .
git clean -f -d
git checkout my_branch
git merge master
git stash pop

Explicación

Comience fusionando master en su sucursal, ya que de todos modos tendrá que hacerlo eventualmente, y ahora es el mejor momento para resolver cualquier conflicto.

La -uopción (aka --include-untracked) en git stash -uevita que pierdas archivos sin seguimiento cuando más tarde lo hagas git clean -f -ddentro demaster .

Después git checkout masteres importante que NO lo hagas git stash pop, porque necesitarás este alijo más tarde. Si usted hace estallar el alijo creada en my_branchy luego haces git stashen master, va a provocar conflictos de fusión innecesarias cuando posteriormente se aplica ese escondite enmy_branch .

git resetdesestabiliza todo lo que resulta de git stash apply. Por ejemplo, los archivos que se han modificado en el alijo pero que no existen enmaster se organizan como conflictos "eliminados por nosotros".

git checkout .y git clean -f -ddescarte todo lo que no está comprometido: todos los cambios en los archivos rastreados y todos los archivos y directorios no rastreados. Ya están guardados en el alijo y, si se dejan master, causarían conflictos de fusión innecesarios al volver a cambiar my_branch.

El último git stash popse basará en el original my_branchy, por lo tanto, no provocará ningún conflicto de fusión. Sin embargo, si su escondite contiene archivos no rastreados que se ha comprometido a dominar, git se quejará de que "No se pudieron restaurar los archivos no rastreados del escondite". Para resolver este conflicto, eliminar los archivos de su árbol de trabajo, a continuación git stash pop, git add .y git reset.

Vladimir Kornea
fuente
2
Su respuesta no se eliminó porque estaba vinculada a su sitio web, se eliminó porque era idéntica a esta otra respuesta de una cuenta diferente. Veo que la otra cuenta tiene el mismo perfil que el tuyo, ¿estás usando dos cuentas? Puede fusionar ambas cuentas. Además, marque un mod para explicar la situación, y puede obtener su respuesta original (con el voto a favor) sin borrar.
1
No puede mantenerlos separados si se fusionan, pero se le permite tener varias cuentas, siempre que no las use para cometer fraude electoral (o que interactúen entre sí en general). Explica tu situación a un mod. Además, la eliminación fue un error honesto, ¿cómo podría esperar que alguien diga que estaba usando dos cuentas diferentes?
3
Debe marcar su publicación y usar la opción Otro para llamar la atención de un mod, a la que no prestará atención cuando edite su respuesta eliminada. Ya he marcado tus publicaciones para atención mod, pero están bastante ocupadas, así que ten paciencia, eventualmente te contactarán.
1
No publique contenido duplicado, particularmente de diferentes cuentas. Vote o marque para cerrar como duplicado si dos preguntas son iguales.
Bill the Lizard