¿Cómo puedo cambiar el nombre de un git stash?

203

Tengo un alijo con un nombre incorrecto. Me gustaría arreglar el nombre para que sea exacto.

¿Cómo puedo cambiar el nombre de un alijo?

mikemaccana
fuente
55
pop y guardarlo de nuevo con un nombre diferente?
Bartlomiej Lewandowski
55
Hacer estallar y guardar de nuevo no siempre es una opción, ya que el almacenamiento puede estar basado en un estado desactualizado y generar conflictos al estallar. (El estado desactualizado ya ni siquiera tiene que existir en ninguna parte de la historia.)
Tom

Respuestas:

259

Supongamos que su lista de escondite se ve así:

$ git stash list
stash@{0}: WIP on master: Add some very important feature 
stash@{1}: WIP on master: Fix some silly bug

Primero, debe eliminar la entrada oculta a la que desea cambiarle el nombre:

$ git stash drop stash@{1}
Dropped stash@{1} (af8fdeee49a03d1b4609f294635e7f0d622e03db)

Ahora solo agrégalo nuevamente con un nuevo mensaje usando sha of commit devuelto después de soltar:

$ git stash store -m "Very descriptive message" af8fdeee49a03d1b4609f294635e7f0d622e03db

Y eso es:

$ git stash list
stash@{0}: Very descriptive message
stash@{1}: WIP on master: Add some very important feature

Esta solución requiere git 1.8.4 o posterior, y sí, también funciona con un directorio de trabajo sucio.

qzb
fuente
3
git show stash@{0}Todavía muestra la información anterior después. ¿Cómo arreglar eso? (Tenga en cuenta que el alijo luego obtiene un SHA diferente.)
Tino
44
Se siente mejor obtener el hash git showy comenzar con git stash store. Luego con git stash listusted verá el viejo y el nuevo alijo. Finalmente puedes limpiar el viejo alijo con git stash drop.
hogi
66
¿git stash drop no perderá los cambios?
Shravya Boggarapu
44
@ShravyaBoggarapu, no, git no elimina commit hasta que git gcse ejecuta. Después de stash dropque pueda encontrar fácilmente esta confirmación normalmente inaccesible mediante el git fsck | grep commitcomando.
qzb
2
@ ÐerÆndi simplemente aplicar y guardar es una opción fácil, pero no funciona cuando los cambios no se pueden volver a aplicar debido a conflictos. Mientras tanto, dejar caer y almacenar obras bajo cualquier circunstancia. He probado mi solución una vez más: funciona bien en la última versión de git (2.17.0).
qzb
62

A menos que lo haga manualmente o contribuya con una mejora a Git, puede usar un alias:

git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git diff-index --quiet HEAD; s=$?; [ $s != 0 ] && git stash save "tmp stash from stash-rename"; git stash apply $rev && shift && git stash save "$@" && [ $s != 0 ] && git stash pop stash@{1}; }; _'

Uso: " git stash-rename <stash> [save options] [<message>]"

Con [save options]cualquier opción de git stash save:[-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] [-u|--include-untracked] [-a|--all]

Ejemplo:

$ git stash list
stash@{0}: On master: Pep8 format
stash@{1}: On master: co other than master with local changes
stash@{2}: On master: tests with deployAtEnd

# Let's say I want to rename the stash@{2} adding an issue reference:
$ git stash-rename stash@{2} NXP-13971-deployAtEnd

$ git stash list
stash@{0}: On master: NXP-13971-deployAtEnd
stash@{1}: On master: Pep8 format
stash@{2}: On master: co other than master with local changes

Eso funcionará incluso si tiene cambios locales no organizados :)

EDITAR 22/02/2016

Script simplificado, créditos a qzb , https://stackoverflow.com/a/35549615/515973

git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git stash store -m "$2" $rev; }; _'

Uso: " git stash-rename <stash> [<message>]"

Julien Carsique
fuente
1
¡Increíble! Aún más git stash-rename 'tests with deployAtEnd' 'NXP-13971-deployAtEnd'
genial
3
entonces la respuesta es 1) limpiar la copia de trabajo, 2) aplicar el alijo que desea renombrar, 3) soltarlo de la lista de alijo, 4) crear un nuevo alijo con el mensaje correcto.
gcb
2
Para aclarar, ¿está cambiando el nombre del último alijo, y después de tal acción se convierte en el alijo superior?
onebree
2
Elimino el alijo para cambiarle el nombre, guardo los cambios actuales, si los hay, vuelvo a crear el alijo eliminado con el nombre deseado y vuelvo a aplicar los cambios actuales, si los hay.
Julien Carsique
3
Esta versión verifica para asegurarse de que ambos argumentos están ahí para que no se caiga accidentalmente su último alijo. También solo requiere el número de alijo, no la stash@{0}referencia completa . gist.github.com/jdforsythe/f248bf6c72fc020225cc3e315a32e922 git config --global alias.stash-rename '!_() { if [ -z \"$1\" ] || [ -z \"$2\" ]; then echo \"git stash-rename 0 NewName\" && echo \"\" && git stash list && exit 1; else stash=\"stash@{$1}\"; rev=$(git rev-parse \"${stash}\"); git stash drop \"${stash}\" || exit 1; git stash store -m \"$2\" \"$rev\" || exit 1; git stash list; fi }; _'
jdforsythe el
6

Es muy simple. Primero, deshaga el último alijo con:

git stash pop

Después de esto, puede guardar el alijo con un nombre personalizado de esta manera:

git stash save "your explanatory name"

Espero que te sea útil. :)

Sandra
fuente
El alijo renombrado puede no ser el más reciente.
mikemaccana
Pulgares arriba ya que esto es más sencillo (SOLO) para el alijo más reciente.
Kaihua
3

No creo que sea posible hacerlo. Ha habido una propuesta para cambiar el nombre de alijo, pero aún no se ha implementado.

Mi idea general es:

  1. Implemente un nuevo git reflog updatecomando que actualice el mensaje asociado con una entrada específica de reflog. Para hacer esto, una nueva update_reflog_ent()función (en reflog.c ) cambiaría el mensaje asociado con la entrada específica de reflog para actualizar. Una update_reflog()función usaría for_each_reflog_ent()con update_reflog_enthacer realidad el cambio.

  2. Un git stash renamecomando solo necesitaría llamar git reflog updatecon la referencia apropiada y el nuevo mensaje.

O podrías, por supuesto, abrir el alijo y hacer un git stash save [message]

A1ternat1ve
fuente
3

Para beneficio del lector, aquí hay una extensión de la respuesta correcta y actualmente aceptada .

Si no solo desea corregir el mensaje oculto y también desea corregir el mensaje de confirmación del ocultamiento, de modo que

git stash list

y

git log --oneline -1 stash

ambos están de acuerdo con lo que se muestra, necesitas un poco más. Puede haber una mejor manera de hacerlo, pero esta receta aquí es fácil de entender, espero.

Para poder hacerlo git commit --amend, debe estar en la CONSEJO de una sucursal. Por lo tanto, la solución es:

git checkout -b scratch stash@{1}
git stash drop stash@{1}
git commit --amend -m "$MESSAGE"
git stash store -m "$MESSAGE" HEAD
git checkout master
git branch -D scratch

Explicado:

  • Cree una nueva rama "scratch" (aún no existente) del "alijo en cuestión" y cámbiela
  • Retira el viejo alijo. Esto es seguro, ya que todavía tenemos esto en la rama.
  • Use git commit --amendpara reemplazar el mensaje de confirmación, esto cambia el SHA del "alijo en cuestión"
  • Almacene el alijo, según la respuesta de qzb
  • Cambiar de nuevo (lo que supone que vino de "maestro") y limpiar

Inconvenientes:

  • Esto cambia las ramas temporalmente. Por lo tanto, esta receta solo se puede aplicar cuando git status --porcelainestá limpia (léase: no genera nada)

  • Renumera los escondites, por lo que el alijo cambiado se convierte stash@{0}

  • Es necesario introducir el $MESSAGEdoble o utilizar alguna variable de entorno (en el ejemplo: MESSAGE)

  • Necesita encontrar un nombre de sucursal no utilizado

Hay formas de hacerlo sin cambiar de rama, pero esto está más allá del alcance de esta respuesta.

Ejemplo

git init scratch
cd scratch
for a in A B C D; do date >$a; git add $a; git commit -m $a; done
for a in X Y; do echo $a > Z; git stash save --all; done
git log --oneline --graph --decorate --all; git stash list

Salida

*-.   e0e281b (refs/stash) WIP on master: 8bdcc32 D
|\ \  
| | * 4d62f52 untracked files on master: 8bdcc32 D
| * 096f158 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: WIP on master: 8bdcc32 D
stash@{1}: WIP on master: 8bdcc32 D

Ahora sin cambiar commit (nota: el SHA a continuación será diferente a su lado):

git stash drop stash@{1}
git stash store -m ...changed... 2fbf9007dfdfb95ae269a19e13b8b9ca3e24181c
git log --oneline --graph --decorate --all; git stash list

Salida

*-.   2fbf900 (refs/stash) WIP on master: 8bdcc32 D
|\ \  
| | * 246dc5c untracked files on master: 8bdcc32 D
| * 80c5ea0 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: ...changed...
stash@{1}: WIP on master: 8bdcc32 D

Como puede ver, stash@{0}todavía se muestra como 2fbf900 (refs/stash) WIP on master: 8bdcc32 Den git log. Si observa detenidamente, verá que varias confirmaciones han cambiado SHA. Esto se debe a cómo se manejan las reservas (los padres están incluidos en el SHA y las reservas tienen sus reservas como padre).

Arregla eso:

git checkout -b scratch stash
git stash drop
git commit --amend -m ...changed...
git stash store -m ...changed... HEAD
git checkout master
git branch -D scratch
git log --oneline --graph --decorate --all; git stash list

Salida

*-.   4d55186 (refs/stash) ...changed...
|\ \  
| | * 246dc5c untracked files on master: 8bdcc32 D
| * 80c5ea0 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: ...changed...
stash@{1}: WIP on master: 8bdcc32 D

Como también puede ver, también refs/stashha cambiado un SHA.

Tino
fuente
Vale la pena mencionar: esto destruye el índice que se guardó con el alijo original, reemplazándolo con un nuevo índice que coincide con la confirmación principal del alijo original. Si uno no planeaba usar el índice original guardado (o ya coincidía con el padre del alijo original), esto no es un problema.
torek
1

Aquí hay una versión modificada del alias de Julien que le permite lidiar adecuadamente con el On <branch>prefijo usualmente antepuesto a los nombres escondidos:

git config --global alias.stash-rename '!_() { newmsg="$1" && stash=${2:-"stash@{0}"} && newbranch="$3" && sha=$(git rev-parse "$stash") && olddesc="$(git stash list --format=%gs -1 "$stash")" && newdesc="$(if [[ "$newbranch" = "." ]]; then echo "$newmsg"; else if [[ -n "$newbranch" ]]; then echo "On $newbranch: $newmsg"; else if [[ "$olddesc" =~ ":" ]]; then echo "$(echo "$olddesc" | cut -f1 -d":"): $newmsg"; else echo "$newmsg"; fi; fi; fi)" && git stash drop "$stash" > /dev/null || exit 1; git stash store -m "$newdesc" "$sha" && git stash list; }; _'

Sintaxis:

git stash-rename <new-name> [<stash> [<new-branch-name> | .]]

Ejemplo de uso:

repo[master] % touch tmp && git add tmp && git stash save first
Saved working directory and index state On master: first
HEAD is now at bd62064 Initial commit
repo[master] % touch tmp && git add tmp && git stash save second
Saved working directory and index state On master: second
HEAD is now at bd62064 Initial commit
repo[master] % git stash list
stash@{0}: On master: second
stash@{1}: On master: first
repo[master] % git stash-rename renamed
stash@{0}: On master: renamed
stash@{1}: On master: first
repo[master] % git stash-rename also-renamed stash@{1}
stash@{0}: On master: also-renamed
stash@{1}: On master: renamed
repo[master] % git stash-rename branch-changed stash@{0} new-branch
stash@{0}: On new-branch: branch-changed
stash@{1}: On master: renamed
repo[master] % git stash-rename branch-name-persists
stash@{0}: On new-branch: branch-name-persists
stash@{1}: On master: renamed
repo[master] % git stash-rename no-branch stash@{0} .
stash@{0}: no-branch
stash@{1}: On master: renamed
repo[master] % git stash-rename renamed
stash@{0}: renamed
stash@{1}: On master: renamed
repo[master] % git stash-rename readd-branch stash@{0} develop
stash@{0}: On develop: readd-branch
stash@{1}: On master: renamed

La mayor parte del comando es para analizar los argumentos y averiguar qué se debe hacer con el nombre de la rama. Las githerramientas utilizadas son las siguientes:

  • git rev-parse <stash> para encontrar el SHA del alijo.
  • git stash list --format=%gs -1 <stash>para encontrar el tema de reflog del alijo. Tenga en cuenta que esto es diferente del mensaje de confirmación del alijo, que este comando no cambia. El tema de reflog es lo que aparece en git stash list, y puede cambiar el tema de reflog sin cambiar los hashes de los commits asociados con los stashes. Sin embargo, siempre puede encontrar el mensaje de confirmación original, ¡así que no lo use git stash-renamepara eliminar información confidencial!
  • git stash drop <stash>para eliminar la referencia anterior al alijo (pero todavía tenemos el SHA, por lo que no se pierde).
  • git stash store -m <new-message> <sha>para guardar una nueva referencia al alijo con la misma información de confirmación pero un tema de registro diferente .
  • git stash listpara enumerar las reservas después de que finalice la operación. Tenga en cuenta que las nuevas reservas siempre se envían al principio de la lista. Sería necesario volver a empujar todos los escondites antes del alijo de interés para restaurar su posición original.
Radon Rosborough
fuente
0

La forma más simple: abre tu alijo con git stash pop y guárdalo de nuevo con git stash guarda tu nombre

Yoel Neuman
fuente
El alijo renombrado puede no ser el más reciente.
mikemaccana