Supprimer temporairement les modifications non validées dans Subversion (a la «git-stash»)

Tout en programmant un logiciel stocké dans un repository Subversion, je modifie souvent certains fichiers, puis remarque que je voudrais apporter des modifications préparatoires à mon travail principal. Par exemple, lors de la mise en œuvre de nouvelles fonctionnalités, je remarque des modifications qui pourraient m’aider.

Afin de ne pas mélanger deux modifications sans rapport, dans ces cas, je voudrais “ranger” mes modifications, c’est-à-dire revenir à la version du référentiel, apporter d’autres modifications, les valider, puis “récupérer” mes modifications.

git-stash permet de faire exactement cela. Y a-t-il un moyen de faire cela avec Subversion, directement ou avec un plugin ou un script. Les plugins Eclipse conviendraient également.

Quand j’ai des modifications non validées d’une tâche dans ma copie de travail et que je dois passer à une autre tâche, je fais l’une des deux choses suivantes:

  1. Découvrez une nouvelle copie de travail pour la deuxième tâche.

    ou

  2. Démarrer une twig:

    workingcopy$ svn copy CURRENT_URL_OF_WORKING_COPY SOME_BRANCH workingcopy$ svn switch SOME_BRANCH workingcopy$ svn commit -m "work in progress" workingcoyp$ svn switch WHATEVER_I_WAS_WORKING_ON_BEFORE 

J’ai des scripts qui aident à automatiser cela.

Ce billet de blog conseille d’utiliser diff et patch.

  • git stash devient approximativement svn diff > patch_name.patch; svn revert -R . svn diff > patch_name.patch; svn revert -R .
  • git stash apply devient le patch -p0 < patch_name.patch

Notez que cela ne cache pas les modifications de métadonnées ou (je pense) les créations / suppressions de répertoires. (Oui, svn suit ceux du répertoire, contrairement à git.)

Vous pouvez stocker vos modifications actuelles avec svn diff dans un fichier patch, puis annuler votre copie de travail:

 svn diff > stash.patch svn revert -R . 

Après avoir implémenté votre fonctionnalité préparatoire, vous pouvez ensuite appliquer votre correctif avec l’utilitaire de correctif:

 patch < stash.patch 

Comme d'autres l'ont noté, cela ne fonctionnera pas avec les opérations svn:properties et tree (ajout, suppression, renommage de fichiers et de répertoires).

Les fichiers binarys peuvent également poser des problèmes, je ne sais pas comment patch (ou TortoiseSVN dans ce cas les gère).

Le plus simple serait d’utiliser une twig temporaire, comme ceci:

 $ svn copy ^/trunk ^/twigs/tempbranch $ svn switch ^/twigs/tempbranch $ svn commit -m "Stashed" $ svn switch ^/trunk $ ... hack away in trunk ... $ svn commit -m "..." $ svn merge ^/twigs/tempbranch . $ svn rm ^/twigs/tempbranch $ ... continue hacking 

Cela pourrait (et devrait probablement) être mis dans un script si cela se fait plus régulièrement.

En 2018-04-13 (Subversion 1.10.0), vous avez une commande svn shelve shelve expérimentale. ( TortoiseSVN prend en charge la commande )

Actuellement, ce n’est rien d’autre qu’une aide pour sauvegarder un patch et l’appliquer, il a donc les mêmes limitations que svn diff + patch (c’est-à-dire qu’il ne peut pas gérer les fichiers binarys et les noms). (Edit: On dirait que le support binary arrive à la prochaine version )

 $ svn shelve --help x-shelve (shelve): Put a local change aside, as if putting it on a shelf. usage: 1. x-shelve [--keep-local] NAME [PATH...] 2. x-shelve --delete NAME 3. x-shelve --list 1. Save the local change in the given PATHs to a patch file, and revert that change from the WC unless '--keep-local' is given. If a log message is given with '-m' or '-F', include it at the beginning of the patch file. 2. Delete the shelved change NAME. (A backup is kept, named with a '.bak' extension.) 3. List shelved changes. Include the first line of any log message and some details about the contents of the change, unless '-q' is given. The kinds of change you can shelve are those supported by 'svn diff' and 'svn patch'. The following are currently NOT supported: mergeinfo changes, copies, moves, mkdir, rmdir, 'binary' content, uncommittable states To bring back a shelved change, use 'svn x-unshelve NAME'. Shelved changes are stored in /.svn/shelves/ The shelving feature is EXPERIMENTAL. This command is likely to change in the next release, and there is no promise of backward compatibility. Valid options: --delete : delete the shelved patch --list : list shelved patches -q [--quiet] : print nothing, or only summary information --dry-run : try operation but make no changes --keep-local : keep path in working copy (...) $ svn unshelve --help x-unshelve (unshelve): Bring a shelved change back to a local change in the WC. usage: 1. x-unshelve [--keep-shelved] [NAME] 2. x-unshelve --list 1. Apply the shelved change NAME to the working copy. Delete the patch unless the '--keep-shelved' option is given. (A backup is kept, named with a '.bak' extension.) NAME defaults to the most recent shelved change. 2. List shelved changes. Include the first line of any log message and some details about the contents of the change, unless '-q' is given. Any conflict between the change being unshelved and a change already in the WC is handled the same way as by 'svn patch', creating a 'reject' file. The shelving feature is EXPERIMENTAL. This command is likely to change in the next release, and there is no promise of backward compatibility. Valid options: --keep-shelved : do not delete the shelved patch --list : list shelved patches -q [--quiet] : print nothing, or only summary information --dry-run : try operation but make no changes (...) 

Je ne connais pas un moyen facile de le faire avec seulement svn. Honnêtement, je vous conseille d’utiliser git-svn pour faire un repo git qui fonctionne comme une copie de travail svn, et en utilisant simplement git stash avec ça. Il suffit de remplacer git pull avec git svn rebase et git push avec git svn dcommit et vous pouvez réellement conserver 90% de votre stream de production git tout en parlant toujours à un serveur svn.

Il existe un petit script Python 2 appelé svn-stash disponible sous GPL 3: https://github.com/frankcortes/svn-stash .

Il fonctionne comme les solutions svn diff/patch mentionnées et propose de pousser et d’extraire les modifications sous forme de diffs dans certains répertoires locaux. Malheureusement, les stashes ne peuvent pas être nommés, et seul le dernier peut être sauté (eh bien, oui, c’est une stack, mais il n’y a pas de raison réelle à une telle limitation). la source.

Il est écrit pour * ix, mais après avoir remplacé tous les “/” par os.sep il fonctionne également sous Windows.

Si vous utilisez svn 1.7 ou supérieur, vous devez changer is_a_current_stash() : supprimez la ligne if ".svn" in os.listdir(CURRENT_DIR): puisqu’il n’y a qu’un seul sous-répertoire .svn de niveau supérieur dans 1.7 WC.

Vous pouvez le faire facilement en utilisant Intellij IDEA – Shelve Changes

Une autre option consiste à copier votre caisse actuelle dans un nouveau répertoire et à annuler toutes vos modifications. De cette façon, vous éviterez de créer une twig temporaire sur votre serveur – après tout, le stockage est une opération locale, que tout le monde ne devrait pas voir et qui peut être effectuée assez souvent.

Après avoir validé votre correctif, vous pouvez mettre à jour votre copie de travail principale et supprimer votre «zone de stockage»

J’ai aussi voulu cette fonctionnalité. J’utilise actuellement TortoiseSVN.

Je n’ai pas trouvé de solution matérielle, sauf pour exporter l’arborescence, revenir au référentiel, effectuer mes modifications et valider, puis comparer les modifications de l’arborescence exscope à mon répertoire contrôlé par source en utilisant un outil tel que Beyond Compare.

Ou, une autre solution pourrait consister à passer du HEAD à un autre répertoire, effectuer vos modifications et la validation. Une fois que vous êtes prêt à les fusionner sur votre autre copie de travail, effectuez une mise à jour et fusionnez vos modifications.

Je garde toujours une seconde caisse, que j’appelle “trunk_clean”. Chaque fois que j’ai besoin de faire un changement rapide et isolé lié à ce que je suis en train de faire, je me contente de passer à la caisse.

Les idées de twigment et de correction ci-dessus sont excellentes, mais elles ne fonctionnent pas bien pour moi. J’utilise un outil de diff visuel, donc l’exécution de git diff ne produit pas de correctifs textuels. Notre système de construction crée un nouvel environnement chaque fois qu’une twig est créée. La création de twigs “temporaires” temporaires serait donc désordonnée.

Au lieu de cela, j’ai écrit un petit script shell qui copie un fichier dans un répertoire “shelf”, ajoute un horodatage et annule la modification. Ce n’est pas aussi robuste que les solutions ci-dessus, mais cela évite également certains des pièges que j’ai rencontrés.

Sur la base de la réponse de Walter, j’ai créé les alias suivants dans mon fichier bashrc:

 alias svn.stash='read -p "saving local changes in raq.patch. Existing stash in raq.patch will be overwritten. Continue?[y/N]" && [[ $REPLY =~ ^[yY] ]] && rm -f raq.patch && svn diff > raq.patch && svn revert -R .' alias svn.stash.apply='patch -p0 < raq.patch; rm -f raq.patch' 

Ces alias sont beaucoup plus faciles à utiliser et à mémoriser.

Usage:

svn.stash pour cacher les modifications et svn.stash.apply pour appliquer le stash.

Utilisation:

 svn cp --parents . ^/trash-stash/my-stash 

Il créera une twig à partir de l’emplacement actuel et de la révision en cours, puis commettra les modifications de la copie de travail sur cette twig sans y accéder.

utilisation: copier SRC [@REV] … DST

SRC et DST peuvent chacun être soit un chemin de copie de travail (WC), soit une URL:

 WC -> URL: immediately commit a copy of WC to URL 

Notez que les modifications apscopes à la copie de travail ne seront pas automatiquement annulées ( cp fait que modifier CoPying vers une nouvelle twig) et vous devez les rétablir manuellement.

Pour restaurer les modifications, vous pouvez simplement fusionner les modifications de la twig nouvellement créée à votre copie de travail.

 svn merge --ignore-ancestry ^/trash-stash/my-stash -c  

--ignore-ancestry est utilisé pour ne pas mettre à jour les informations de fusion dans la copie de travail.

Utilisation:

 svn ls -v ^/trash-stash/ 

pour voir ce que vous avez sur le chemin caché. Les révisions validées sont également imprimées.

Si vous n’avez plus besoin du cache, lancez simplement:

 svn rm ^/trash-stash/my-stash 

Cette solution est préférable à l’utilisation de correctifs, car si de nouvelles modifications de la copie de travail ou de la twig en cours entrent en conflit avec les modifications du cache, vous pouvez résoudre les conflits à l’aide de svn means, .

Dans ma pratique, j’utilise git init pour créer un repository Git dans le répertoire du trunk de mon repository Subversion, puis j’ajoute *.git aux Suctions ignore patterns.

Après avoir modifié certains fichiers, si je veux continuer mon travail avec la ligne principale de Subversion, j’utilise simplement git stash pour cacher mon travail. Après m’être engagé dans le repository Subversion, j’utilise git stash pop pour restaurer mes modifications.