Guardar solo cambios no organizados en Git


229

Me gustaría hacer el siguiente flujo de trabajo:

  1. Agregar cambios al escenario.
  2. Guarda todos los demás cambios que no se organizaron.
  3. Haga algunas cosas con las cosas en el escenario (es decir, compilar, ejecutar pruebas, etc.)
  4. Aplica el alijo.

¿Hay alguna manera de hacer el paso 2?

Ejemplo

 echo "123" > foo
 git add foo # Assumes this is a git directory
 echo "456" >> foo
 git stash
 cat foo # Should yield 123

¿Por qué no comprometer sus cambios después de organizarlos?
Shizzmo

3
IIRC --keepindex hace exactamente eso
sehe

44
Porque si, por ejemplo, la compilación falla, no quiero tener una confirmación de esto. Sé que puedo eliminar el commit, pero me gustaría hacerlo sin un commit si es posible.
Unapiedra

Sehe, gracias. Puedo confirmar que esto funciona. Vaya, miré el manual en linux.die.net/man/1/git-stash que está desactualizado. man git stashes mucho mejor.
Unapiedra

es --keep-index, fwiw.
jaf0

Respuestas:


288

git stash savetiene una opción --keep-indexque hace exactamente lo que necesitas.

Entonces, corre git stash save --keep-index.


99
Cierto. Sigo usando savecon git stash. Tal vez es el programador en mí que insiste en honrar la simetría con apply / pop. :)
vhallac

104
Nota: esto todavía oculta todos sus cambios; La única diferencia con respecto a la regular git stash savees que también deja los cambios ya organizados en su copia de trabajo. En el flujo de trabajo anterior, esto funcionaría bien ya que solo está aplicando el alijo encima de una copia local que ya tiene la mitad de los cambios del alijo (que git es lo suficientemente inteligente como para ignorarlo). Pero si edita el código antes de volver a aplicar el alijo, podría ver conflictos de fusión cuando vaya a aplicar. Fyi.
peterflynn

2
@ytpete Eso me ha mordido muchas veces. Realmente desearía que git pudiera esconder las cosas que no estás guardando ... A menudo cometo cosas, luego hago un escondite completo de git, sabiendo que puedo git commit --ammendsi hay problemas en lo que cometí.
rjmunro

1
--amend(en lugar de --ammend)
Ruibarbo

19
Esta solución no me funciona debido a los problemas descritos por peterflynn. No es una buena respuesta a la pregunta, ya que aún oculta los cambios organizados. ¿Alguien tiene una mejor solución?
user643011

43

Esto puede hacerse en 3 pasos: guardar los cambios por etapas, guardar todo lo demás, restaurar el índice con los cambios por etapas. Que es básicamente:

git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^

Esto hará exactamente lo que quieras.


3
Nota: -utambién guarda archivos sin seguimiento.
ma11hew28

Este enfoque esencialmente duplica lo que git stash save --keep-indexhace con mucho más trabajo. No veo ninguna ventaja.
Iñigo

1
@vas No, el enfoque no duplica eso. Vea el comentario de peterflynn a la respuesta aceptada.
Alexander Klauer

28
git stash save --keep-index

Además, Re:

¿Por qué no comprometer sus cambios después de organizarlos? - Espinilla

R: Porque siempre debe registrar el código probado :) Eso significa que debe ejecutar las pruebas solo con los cambios que está a punto de confirmar.

Todo esto, aparte del hecho de que, por supuesto, como programador experimentado, tienes la necesidad innata de probar y revisar solo esos cambios, solo una broma parcial


14

Con git version 2.7.4usted puede hacer:

git stash save --patch

El gitle pedirá que agregue o no sus cambios en el alijo.
Y luego solo respondes yon

Puede restaurar el directorio de trabajo como siempre lo hace:

git stash pop

o, si desea mantener los cambios guardados en el alijo:

git stash apply

Esto es asombroso Es un poco laborioso, pero al menos puede omitir y agregar archivos completos.
Dustin Oprea

5

Al extender las respuestas anteriores, a veces tengo un conjunto complejo de cambios organizados, pero deseo realizar un cambio por separado primero. Por ejemplo, podría haber detectado un error o un código incorrecto que me gustaría corregir antes de mis cambios organizados. Una posible ruta a seguir es esta:

primero esconde todo, pero deja los cambios organizados intactos

$ git stash save --keep-index [--include-untracked]

ahora esconde los cambios organizados por separado también

$ git stash save

hacer cambios para arreglar; y prueba; comprometerlos:

$ git add [--interactive] [--patch]

$ git commit -m "arreglar ..."

ahora restaure los cambios organizados previamente:

$ git stash pop

resuelva cualquier conflicto y tenga en cuenta que si hubo conflictos, git se aplicará pero no eliminará esa entrada de alijo superior.

(... Luego, confirme los cambios organizados y restaure el alijo de todos los demás cambios, y continúe ...)


4

Para agregar los archivos no escalonados (no agregados a commit) a stash, ejecute el siguiente comando:

git stash -k

Entonces puede confirmar los archivos almacenados. Después de eso, puede recuperar los últimos archivos escondidos con el comando:

git stash pop

4

Esconder solo el árbol de trabajo (cambios no organizados) en Git es más difícil de lo que debería ser. La respuesta aceptada oculta los cambios no organizados, pero también oculta los cambios organizados (y los deja también organizados), que rara vez es lo que desea.

Este alias funciona bien:

stash-working = "!f() { \
  git commit --quiet -m \"temp for stash-working\" && \
  git stash push \"$@\" && \
  git reset --quiet --soft HEAD~1; }; f"

Confirma los cambios por etapas temporalmente, crea un alijo a partir de los cambios restantes (y permite que argumentos adicionales como --include-untrackedy --messagese pasen como argumentos de alias), y luego restablece la confirmación temporal para recuperar los cambios por etapas.

Es similar a la respuesta de @Simon Knapp , pero con algunas diferencias menores: se utiliza --quieten las acciones temporales tomadas y acepta cualquier número de parámetros para el alijo push, en lugar de codificarlo -m, y se agrega --softal final restablecer para que el índice permanezca como comenzó.

Para el problema opuesto de guardar solo los cambios por etapas (alias stash-index), vea esta respuesta .


2

Otro consejo, relacionado con la pregunta:

Cuando guardas de manera efectiva tus cambios no organizados usando

$ git stash save --keep-index

es posible que desee enviar un mensaje al alijo, de modo que cuando lo haga git stash list, sea más obvio lo que ha guardado antes, especialmente si sigue esa operación de alijo con más salvamentos. Por ejemplo

$ git stash save --keep-index "cambios aún no organizados"

(aunque en realidad contiene todos los cambios como se indica en otras respuestas).

Por ejemplo, lo anterior podría ser seguido inmediatamente por:

$ git stash save "cambios por etapas para la función X"

Tenga cuidado, sin embargo, que no puede usar

$ git stash apply "stash @ {1}" ### ✘ no hace lo que quieres

para restaurar solo los cambios no organizados.


2

Git no tiene un comando que oculte solo tus cambios no organizados.

Sin embargo, Git te permite especificar qué archivos quieres guardar.

git stash push --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

Si solo desea guardar cambios específicos en esos archivos, agregue la --patchopción.

git stash push --patch --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

La --include-untrackedopción le permite guardar archivos sin seguimiento.

git stash push --include-untracked --message 'Untracked files' -- app/controllers/widgets_controller.rb test/controllers/widgets_controller_test.rb

Ejecute git help stash(o man git-stash) para obtener más información.

Nota: Si sus cambios no organizados están bastante desorganizados, la respuesta de @ alesguzik probablemente sea más fácil.


0

La forma moderna de ese comando es git stash push [--] [<pathspec>...], ya que Git 2.16+ ( git stash saveestá en desuso )

Puede combinar eso con un formulario comodín, por ejemplo:

git stash push --all --keep-index ':(glob)**/*.testextension' 

Pero eso no funciona bien con Git para Windows, hasta Git 2.22 (Q2 2019), vea el problema 2037 , considerando que git stashse ha vuelto a implementar en C (en lugar de un script de shell)

Ver commit 7db9302 (11 mar 2019) por Thomas Gummerer ( tgummerer) .
Ver commit 1366c78 , commit 7b556aa (07 mar 2019) por Johannes Schindelin ( dscho) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 0ba1ba4 , 22 abr 2019)

incorporado stash: manejar :(glob)nuevamente las especificaciones de ruta

Al pasar una lista de rutas de acceso a, digamos, git adddebemos tener cuidado de usar la forma original, no la forma analizada de las rutas de acceso.

Esto hace la diferencia, por ejemplo, al llamar

git stash -- ':(glob)**/*.txt'

donde el formulario original incluye el :(glob)prefijo mientras que el formulario analizado no.

Sin embargo, en el incorporado git stash, pasamos el formulario analizado (es decir, incorrecto) y git addfallamos con el mensaje de error:

fatal: pathspec '**/*.txt' did not match any files

en la etapa en git stashla que se eliminan los cambios del árbol de trabajo, incluso si refs/stashrealmente se ha actualizado con éxito.


0

Utilizo un alias, que acepta una cadena para usar como mensaje en la entrada oculta.

mystash = "!f() { git commit -m hold && git stash push -m \"$1\" && git reset HEAD^; }; f"

Cual:

  • compromete todo en el índice,
  • oculta lo que ha cambiado en el árbol de trabajo (por supuesto, podría agregar -uo -a),
  • restablece el último commit al intento de trabajo (puede usarlo --softpara mantenerlo en el índice).
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.