Commande Git pour enregistrer une réserve sans modifier l’arbre de travail?

J’ai voulu utiliser une commande git qui sauve une réserve sans modifier mon arbre de travail, comme une sauvegarde légère, à l’abri de toute réinitialisation de git ou de tout ce que je ferais pour bousiller mon index. Fondamentalement, l’équivalent fonctionnel de «git stash save && git stash» s’applique, sauf que la copie de travail n’est jamais touchée, car cela peut rendre certains éditeurs de texte / IDE de mauvaise qualité.

Quelque chose comme ça se rapproche de ce que je veux, mais pas tout à fait:

git update-ref refs/stash `git stash create "Stash message"` 

Cela fonctionne fonctionnellement, mais le problème que j’ai, c’est qu’aucun message caché n’apparaît dans “git stash list”, même si le commit contient effectivement mon message. Compte tenu de l’ampleur que peut avoir une réserve, les messages cachés sont très importants.

Grâce au conseil de Charles, j’ai créé un script bash pour faire exactement ce que je voulais (je rencontrais des problèmes pour l’implémenter comme un simple alias). Il faut un message de réserve optionnel, tout comme git stash save. Si aucun n’est fourni, il utilisera le message par défaut généré par git stash.

 #!/bin/sh # # git-stash-snap # Save snapshot of working tree into the stash without modifying working tree. # First argument (optional) is the stash message. if [ -n "$1" ]; then git update-ref -m "$1" refs/stash "$(git stash create \"$1\")" else HASH=`git stash create` MESSAGE=`git log --no-walk --pretty="tformat:%-s" "$HASH"` git update-ref -m "$MESSAGE" refs/stash "$HASH" fi 

Edit: Comme indiqué dans un commentaire ci-dessous, enregistrer ce script sous le nom git-stash-snap quelque part dans votre chemin est suffisant pour pouvoir l’invoquer en tapant git stash-snap .

La bonne chose ici est que même si vous déposez une réserve faite avec cette méthode, vous pourrez toujours voir le message caché en utilisant git log [commit-hash] du commit en suspens!

Edit: depuis git 2.6.0, vous pouvez append --create-reflog à update-ref et la git stash list l’affichera même si git stash n’était pas utilisé auparavant.

Edit: Git a introduit une nouvelle sous-commande stash appelée stash push , j’ai donc mis à jour ma recommandation pour nommer ce script de git-stash-push à git-stash-snap .

Vous devez transmettre le message à update-ref , et non pas stash create car stash create ne prend pas de message (il ne met à jour aucune référence, donc il n’y a pas d’entrée de reflog à remplir).

 git update-ref -m "Stash message" refs/stash "$(git stash create)" 

Inspiré par la solution d’Eliot, j’ai un peu prolongé son script:

 #!/bin/sh # # git-stash-push # Push working tree onto the stash without modifying working tree. # First argument (optional) is the stash message. # # If the working dir is clean, no stash will be generated/saved. # # Options: # -c "changes" mode, do not stash if there are no changes since the # last stash. if [ "$1" == "-c" ]; then CHECK_CHANGES=1 shift fi if [ -n "$1" ]; then MESSAGE=$1 HASH=$( git stash create "$MESSAGE" ) else MESSAGE=`git log --no-walk --pretty="tformat:%-s" "HEAD"` MESSAGE="Based on: $MESSAGE" HASH=$( git stash create ) fi if [ "$CHECK_CHANGES" ]; then # "check for changes" mode: only stash if there are changes # since the last stash # check if nothing has changed since last stash CHANGES=$( git diff stash@{0} ) if [ -z "$CHANGES" ] ; then echo "Nothing changed since last stash." exit 0 fi fi if [ -n "$HASH" ]; then git update-ref -m "$MESSAGE" refs/stash "$HASH" echo "Working directory stashed." else echo "Working tree clean, nothing to do." fi 

J’ai implémenté les modifications suivantes dans le script d’Eliot:

  1. Lorsque le répertoire de travail est propre, le script sortira gracieusement
  2. Lorsque switch -c est utilisé, s’il n’y a pas de changement par rapport au dernier, le script se ferme. Ceci est utile si vous utilisez ce script comme une “machine à remonter le temps”, en effectuant une réserve automatique toutes les 10 minutes. Si rien n’a changé, aucune nouvelle réserve n’est créée. Sans ce commutateur, vous pourriez vous retrouver avec n stashes consécutifs qui sont les mêmes.

Non pas que pour que le commutateur -c fonctionne correctement, au moins un stash doit exister, sinon le script génère une erreur sur git diff stash@{0} et ne fera rien.

J’utilise ce script comme une “time machine”, en snapshot toutes les 10 minutes en utilisant la boucle bash suivante:

  while true ; do date ; git stash-push ; sleep 600 ; done