git-stash contre git-branch

92

Dans une question précédente sur Git , Daniel Benamy parlait d'un workflow dans Git:

Je travaillais sur master et j'ai commis des trucs, puis j'ai décidé de mettre ce travail en attente. J'ai sauvegardé quelques commits, puis je me suis ramifié avant de commencer mon travail de merde.

Il voulait restaurer son état de fonctionnement à un point antérieur dans le temps sans perdre ses modifications actuelles. Toutes les réponses tournaient autour, de différentes manières, quelque chose comme

git branch -m master crap_work
git branch -m previous_master master

Comment cela se compare- git stasht-il? Je suis un peu confus en essayant de voir quels sont les différents cas d'utilisation ici quand il semble que tout git stashest déjà géré par branchement ...


@ Jordi Bunster : Merci, cela clarifie les choses. Je suppose que je considérerais en quelque sorte le "stashing" comme une branche légère et sans nom. Donc, tout ce que le stash peut faire, la branche le peut aussi mais avec plus de mots. Agréable!

Will Robertson
la source

Réponses:

109

'stash' prend les éléments non validés et " sales " sur votre copie de travail, et les cache, vous laissant une copie de travail propre.

Il n'y a pas vraiment de branche du tout. Vous pouvez ensuite appliquer la réserve au-dessus de n'importe quelle autre branche. Ou, à partir de Git 1.6, vous pouvez faire:

git stash branch <branchname> [<stash>]

pour appliquer le stash sur une nouvelle branche, le tout en une seule commande.

Ainsi, stash fonctionne très bien si vous ne vous êtes pas encore engagé dans la " mauvaise " branche.

Si vous vous êtes déjà engagé, le flux de travail que vous décrivez dans votre question est une meilleure alternative. Et au fait, vous avez raison: Git est très flexible, et cette flexibilité s'accompagne de fonctionnalités qui se chevauchent.

Jordi Bunster
la source
1
une chose qui me mord ... pouvez-vous écrire à quoi ressemble réellement un [<stash>]! Ils l'ont mis dans cette notation dans la documentation, mais il n'est pas évident de savoir si cela devrait être 1 ou @ {1} ou quoi.
Gregg Lind
1
Si vous voulez faire référence à une cachette spécifique "N", utilisez la cachette @ {N}
Jordi Bunster
9
Consultez git stash listles noms de vos cachettes.
idbrii
6
Gregg, oui vous pouvez: git stash save (nom de votre stash). Le rend beaucoup plus utile si vous l'utilisez beaucoup afin que vous sachiez ce que fait chaque cachette. Vous pouvez utiliser git stash show -p (nom) pour vous montrer le patch d'un stash.
Thomas Vander Stichele
7
également, git stash show -upour afficher une différence de la réserve par rapport à la copie de travail.
ken le
49

Lorsque vous restaurez votre réserve, vos modifications sont réappliquées et vous continuez à travailler sur votre code.

Pour cacher vos modifications actuelles

$ git stash save 
Saved "WIP on master: e71813e..."

Vous pouvez également avoir plusieurs réserves. La réserve fonctionne comme une pile. Chaque fois que vous enregistrez une nouvelle réserve, elle est placée au-dessus de la pile.

$ git stash list
stash@{0}: WIP on master: e71813e..."

Notez la stash@{0}partie? C'est votre identifiant de cachette. Vous en aurez besoin pour le restaurer plus tard. Faisons ça maintenant. L'ID de la réserve change à chaque fois que vous créez une réserve. stash @ {0} fait référence à la dernière cache que vous avez créée.

Pour appliquer une réserve

$ git stash apply stash@{0}

Vous remarquerez peut-être que la réserve est toujours là après l'avoir appliquée. Vous pouvez le laisser tomber si vous n'en avez plus besoin.

$ git stash drop stash@{0}

Ou, parce que la réserve agit comme une pile, vous pouvez sortir la dernière réserve que vous avez enregistrée:

$ git stash pop

Si vous voulez effacer toutes vos cachettes, exécutez la commande 'clear':

$ git stash clear

Il se peut très bien que vous n'utilisiez pas souvent de cachettes. Si vous souhaitez simplement stocker rapidement vos modifications pour les restaurer ultérieurement, vous pouvez omettre l'ID de cache.

$ git stash
...
$ git stash pop

N'hésitez pas à expérimenter la réserve avant de l'utiliser sur des travaux vraiment importants.

J'ai également une version plus détaillée de ceci publiée sur mon blog .

Ariéjan
la source
une ressource beaucoup plus utile que la supposée `` meilleure '' réponse ... (bien que la meilleure réponse l'ait fait beaucoup plus clair, il y avait quelques confusions concernant l'utilisation complète)
kumarharsh
9

Je me méfie toujours de git stash. Si vous vous cachez plusieurs fois, les choses ont tendance à se compliquer. git stash list affichera une liste numérotée des stashs que vous avez créés, avec des messages si vous les avez fournis ... Mais le problème réside dans le fait que vous ne pouvez pas nettoyer les stashs sauf avec un brutal git stash clear (qui les supprime tous) . Donc, à moins que vous ne soyez toujours anal en donnant des messages super-descriptifs pour vos cachettes (un peu va à l'encontre de la philosophie de stash), vous vous retrouvez avec un tas de cachettes incompréhensibles.

Le seul moyen que je connaisse pour déterminer lequel est d'utiliser gitk --all et repérer les cachettes. Au moins, cela vous permet de voir sur quel commit le stash a été créé, ainsi que la différence de tout ce qui est inclus dans ce stash.

Notez que j'utilise git 1.5.4.3, et je pense que 1.6 ajoute git stash pop, qui, je suppose, appliquerait le stash sélectionné et supprimerait de la liste. Ce qui semble beaucoup plus propre.

Pour l'instant, j'essaie toujours de me brancher à moins que je ne sois absolument sûr que je vais revenir à cette cachette le même jour, même dans l'heure.

webmat
la source
3
Faites-vous des branches sans leur donner de noms utiles? Sinon, je ne vois pas pourquoi vous ne faites pas la même chose avec le stash. Si vous voulez vraiment savoir ce qu'ils contiennent, utilisez simplement git-stash show pour afficher les fichiers modifiés, ou git-stash apply et git-diff pour voir les différences réelles. Garder les réserves coupées revient au même que garder vos branches sous contrôle.
Xiong Chiamiov
18
en fait, vous pouvez supprimer une seule réserve en utilisantgit stash drop [<stash>]
kumarharsh
1
Certes, git a eu git stash drop depuis longtemps maintenant. C'est beaucoup moins un PITA à utiliser maintenant. Je l'utilise tous les jours, et même sur de longues périodes de temps, maintenant.
webmat
3

Si vous recherchez un flux de travail qui peut être plus approprié que git stash, vous voudrez peut-être regarder git-bottle . C'est un utilitaire dans le but de sauvegarder et de restaurer les différents états de travail de git en tant que commits normaux de git, en instantané de manière efficace l'état actuel et pertinent de votre arbre de travail et tout différents états de fichier affichés sous git status.

Principales différences avec git stash:

  • git stashenregistre étroitement l'état git sale (fichiers modifiés et fichiers ajoutés dans l'index), alors qu'il git-bottleest conçu pour enregistrer tout ce qui est différent de HEAD, et il différencie de manière conservatrice entre les chemins modifiés, modifiés et non ajoutés, non ajoutés, non fusionnés, et les états de rebase / fusion complets (seuls les chemins sous .gitignorene sont pas enregistrés).
  • git stashenregistre les objets dont vous avez besoin pour garder une trace séparément. Si j'ai caché quelque chose il y a 2 semaines, je ne m'en souviendrai peut-être pas, alors que les git-bottlesauvegardes en tant que commits provisoires dans la branche actuelle . L'action inverse git-unbottleest l'équivalent de la git stashpop. Il est possible de pousser et de partager ces commits entre les référentiels. Cela peut être utile pour les versions distantes, où vous avez un autre référentiel dans un serveur distant uniquement pour la construction, ou pour collaborer avec d'autres personnes sur la résolution de conflits.
Dan Aloni
la source