Comment renommer une cachette git?

203

J'ai une cachette avec un nom incorrect. Je voudrais corriger le nom pour qu'il soit précis.

Comment renommer une stash?

mikemaccana
la source
5
pop-le et enregistrez-le à nouveau avec un nom différent?
Bartlomiej Lewandowski
5
Le popping et le stashing à nouveau ne sont pas toujours une option, car le stash peut être basé sur un état obsolète et entraîner des conflits lors du popping. (L'état obsolète n'a même plus besoin d'exister nulle part dans l'histoire.)
Tom

Réponses:

259

Supposons que votre liste de dissimulations ressemble à ceci:

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

Tout d'abord, vous devez supprimer l'entrée cachée que vous souhaitez renommer:

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

Maintenant, ajoutez-le à nouveau avec un nouveau message en utilisant sha de commit retourné après la suppression:

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

Et c'est tout:

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

Cette solution nécessite git 1.8.4 ou une version ultérieure, et oui, elle fonctionne également avec un répertoire de travail sale.

qzb
la source
3
git show stash@{0}affiche toujours les anciennes informations par la suite. Comment y remédier? (Veuillez noter que la cachette obtient alors un SHA différent.)
Tino
4
Il est préférable d'obtenir le hachage git showet de commencer git stash store. Ensuite, git stash listvous verrez l'ancienne et la nouvelle cachette. Enfin, vous pouvez nettoyer l'ancienne cachette avec git stash drop.
hogi
6
git stash drop ne perdra-t-il pas les modifications?
Shravya Boggarapu
4
@ShravyaBoggarapu, non, git ne supprime pas le commit jusqu'à ce qu'il git gcsoit exécuté. Après, stash dropvous pouvez facilement trouver ce commit normalement inaccessible à l'aide de la git fsck | grep commitcommande.
qzb
2
@ ÐerÆndi simplement appliquer et enregistrer est une option facile, mais ne fonctionne pas lorsque les modifications ne peuvent pas être réappliquées en raison de conflits. Pendant ce temps, la suppression et le stockage des œuvres en toutes circonstances. J'ai testé ma solution une fois de plus - cela fonctionne très bien sur la dernière version de git (2.17.0).
qzb
62

Sauf si vous le faites manuellement ou apportez une amélioration à Git, vous pouvez utiliser 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}; }; _'

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

Avec [save options]n'importe quelle option de git stash save:[-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] [-u|--include-untracked] [-a|--all]

Exemple:

$ 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

Cela fonctionnera même si vous avez des modifications locales non mises en scène :)

EDIT 2016/02/22

Script simplifié, crédits à 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; }; _'

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

Julien Carsique
la source
1
Impressionnant! Encore plus cool si vous pouviez le fairegit stash-rename 'tests with deployAtEnd' 'NXP-13971-deployAtEnd'
mikemaccana
3
la réponse est donc 1) nettoyer la copie de travail, 2) appliquer la cachette que vous souhaitez renommer, 3) la supprimer de la liste des cachettes, 4) créer une nouvelle cachette avec le bon message.
gcb
2
Pour clarifier, vous renommez la dernière cachette, et après une telle action, elle devient la cachette supérieure?
onebree
2
Je supprime la cachette à renommer, enregistre les modifications actuelles le cas échéant, recrée la cachette supprimée avec le nom souhaité, réapplique les modifications actuelles le cas échéant.
Julien Carsique
3
Cette version vérifie que les deux arguments sont là pour ne pas simplement laisser tomber votre dernière cachette accidentellement. Il ne requiert également que le numéro de réserve, pas la stash@{0}référence entière . 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
6

C'est très simple. Tout d'abord, annulez la dernière cachette avec:

git stash pop

Après cela, vous pouvez enregistrer la cachette avec un nom personnalisé de cette façon:

git stash save "your explanatory name"

J'espère que cela vous sera utile. :)

Sandra
la source
La cachette renommée n'est peut-être pas la plus récente.
mikemaccana
Bravo depuis ce plus simple (UNIQUEMENT) pour la dernière cachette.
Kaihua
3

Je ne pense pas que ce soit possible. Il a été proposé de renommer la cachette, mais elle n'a pas encore été mise en œuvre.

Mon idée générale est:

  1. Implémentez une nouvelle git reflog updatecommande qui met à jour le message associé à une entrée de reflog spécifique. Pour ce faire, une nouvelle update_reflog_ent()fonction (dans reflog.c ) changerait le message associé à l'entrée de reflog spécifique à mettre à jour. Une update_reflog()fonction utiliserait for_each_reflog_ent()avec update_reflog_entpour effectuer le changement.

  2. Une git stash renamecommande n'aurait alors besoin que d'appeler git reflog updateavec la référence appropriée et le nouveau message.

Ou vous pouvez, bien sûr, sauter la cachette et faire un git stash save [message]

A1ternat1ve
la source
3

Pour le bénéfice du lecteur, voici une extension de la réponse correcte et acceptée actuellement .

Si vous souhaitez non seulement corriger le message de dissimulation et également corriger le message de validation de la dissimulation, de telle sorte que

git stash list

et

git log --oneline -1 stash

les deux sont d'accord sur ce qui est montré, il vous en faut un peu plus. Il pourrait y avoir une meilleure façon de le faire, mais cette recette ici est facile à comprendre, j'espère.

Pour pouvoir le faire, git commit --amendvous devez être sur le TIP d'une succursale. La solution est donc:

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

Expliqué:

  • Créez une nouvelle branche "scratch" (pas encore existante) à partir de la "cachette en question" et passez à celle-ci
  • Retirez l'ancienne cachette. C'est sûr, car nous l'avons toujours sur la branche.
  • Utilisez git commit --amendpour remplacer le message de validation, ce qui modifie le SHA de la "cachette en question"
  • Stockez la cachette, en fonction de la réponse du qzb
  • Revenez en arrière (ce qui suppose que vous venez du "maître") et nettoyez

Désavantages:

  • Cela change temporairement de branche. Cette recette ne peut donc être appliquée que lorsqu'elle git status --porcelainest propre (lire: ne produit rien)

  • Il renumérote les cachettes, donc la cachette changée devient stash@{0}

  • Vous devez entrer le $MESSAGEdouble ou utiliser une variable d'environnement (dans l'exemple: MESSAGE)

  • Vous devez trouver un nom de branche inutilisé

Il existe des moyens de le faire sans changer de branche, mais cela dépasse le cadre de cette réponse.

Exemple

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

Production

*-.   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

Maintenant sans changer de commit (note: le SHA suivant sera différent à vos côtés):

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

Production

*-.   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

Comme vous pouvez le voir, l'image stash@{0}est affichée comme 2fbf900 (refs/stash) WIP on master: 8bdcc32 Ddans git log. Si vous regardez attentivement, vous verrez que plusieurs validations ont changé SHA. Cela est dû à la façon dont les cachettes sont gérées (les parents sont inclus dans la SHA et les cachettes ont leurs cachettes en tant que parent).

Répare ça:

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

Production

*-.   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

Comme vous pouvez également le voir, le refs/stashSHA a également changé.

Tino
la source
À noter: cela détruit l'index qui a été enregistré avec la cachette d'origine, en le remplaçant par un nouvel index qui correspond à la validation parent de la cachette d'origine. Si l'on ne prévoyait pas d'utiliser l'index enregistré d'origine (ou qu'il correspondait déjà au parent de la cachette d'origine), ce n'est pas un problème.
torek
1

Voici une version modifiée de l'alias de Julien qui vous permet de gérer correctement le On <branch>préfixe généralement ajouté au début pour cacher les noms:

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; }; _'

Syntaxe:

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

Exemple d'utilisation:

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 plupart de la commande sert à analyser les arguments et à déterminer ce qui doit être fait pour le nom de la branche. Les gitoutils utilisés sont les suivants:

  • git rev-parse <stash> pour trouver le SHA de la cachette.
  • git stash list --format=%gs -1 <stash>pour trouver le sujet reflog de la cachette. Notez que ceci est différent du message de validation de la cachette, qui n'est pas modifié par cette commande. Le sujet de reflog est ce qui apparaît git stash listet vous pouvez changer le sujet de reflog sans changer les hachages des commits associés aux stashes. Cependant, vous pouvez toujours trouver le message de validation d'origine, alors ne l'utilisez pas git stash-renamepour supprimer des informations sensibles!
  • git stash drop <stash>pour supprimer l'ancienne référence à la cachette (mais nous avons toujours le SHA, il n'est donc pas perdu).
  • git stash store -m <new-message> <sha>pour enregistrer une nouvelle référence à la cachette avec les mêmes informations de validation mais un sujet de reflog différent .
  • git stash listpour lister les stashes une fois l'opération terminée. Notez que les nouveaux stashes sont toujours poussés au début de la liste. Il faudrait repousser toutes les cachettes avant la cachette d'intérêt afin de rétablir sa position d'origine.
Radon Rosborough
la source
0

Manière la plus simple: faites éclater votre cachette avec git stash pop puis enregistrez-la à nouveau avec git stash sauvegardez votre nom

yoel neuman
la source
La cachette renommée n'est peut-être pas la plus récente.
mikemaccana