web-dev-qa-db-fra.com

Temporairement mettre de côté les modifications non engagées dans Subversion (à la manière de "stit git")

Lors de la programmation de logiciels stockés dans un dépôt Subversion, je modifie souvent certains fichiers, puis remarque que je souhaite apporter des modifications préparatoires à mon travail principal. Par exemple. lors de la mise en œuvre de nouvelles fonctionnalités, je remarque une refactorisation qui pourrait m'aider.

Afin de ne pas mélanger deux modifications non liées, dans ce cas, j'aimerais "ranger" mes modifications, c'est-à-dire revenir à la version du référentiel, effectuer d'autres modifications, les valider, puis "récupérer" mes modifications.

git-stash permet de faire exactement cela. Est-il possible de le faire avec Subversion, directement ou avec un plugin ou un script? Les plugins Eclipse seraient également bien.

302
sleske

Lorsque 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. Extraire une nouvelle copie de travail pour la deuxième tâche.

    ou

  2. Démarrer une branche:

    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.

67
bendin

Cet article de blog conseille d'utiliser diff et patch.

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

Notez que cela ne cache pas les changements de métadonnées ou (je pense) que le répertoire ne crée/supprime. (Oui, svn les suit séparément du contenu du répertoire, contrairement à git.)

323
Walter Mundt

Vous pouvez stocker vos modifications actuelles avec svn diff dans un fichier de correctif, puis revenez à votre copie de travail:

svn diff > stash.patch
svn revert -R .

Une fois que vous avez mis en œuvre 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 svn:properties et des opérations d’arborescence (ajouter, supprimer, renommer des fichiers et des répertoires).

Les fichiers binaires peuvent aussi donner des problèmes, je ne sais pas comment patch (ni TortoiseSVN dans ce cas les gère).

172
knittl

Le moyen le plus simple serait d'utiliser une branche temporaire, comme ceci:

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

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

42
JesperE

Depuis 1.10.0 (2018-04-13), vous avez expérimental svn shelve commande . ( TortoiseSVN supporte la commande ) Ce n'est qu'un assistant pour enregistrer un patch et le réappliquer. Il a donc les mêmes limitations que svn diff + patch (je ne peux pas gérer les fichiers binaires ni les renommer). ( Edit: On dirait que le support binaire arrive à la prochaine version 1.11. )

Edit ^ 2: Avec 1.11.0 (publié le 2018-10-30), les fichiers binaires sont pris en charge . Les fichiers renommés en rack ne sont toujours pas pris en charge. Les étagères dans 1.11 sont incompatibles avec les étagères créées par 1.10.

Edit ^ 3: Avec 1.12.0 (publiée le 2019-04-24), la copie et le changement de nom sont pris en charge . Les étagères de la version 1.12 sont incompatibles avec les étagères créées par les versions précédentes.

Les notes de conception sont disponibles chez les développeurs Wiki .

$ svn x-shelve --help
x-shelve: Move local changes onto a shelf.
usage: x-shelve [--keep-local] SHELF [PATH...]

  Save the local changes in the given PATHs to a new or existing SHELF.
  Revert those changes from the WC unless '--keep-local' is given.
  The shelf's log message can be set with -m, -F, etc.

  'svn shelve --keep-local' is the same as 'svn shelf-save'.

  The kinds of change you can shelve are committable changes to files and
  properties, except the following kinds which are not yet supported:
     * copies and moves
     * mkdir and rmdir
  Uncommittable states such as conflicts, unversioned and missing cannot
  be shelved.

  To bring back shelved changes, use 'svn unshelve SHELF'.

  Shelves are currently stored under <WC>/.svn/experimental/shelves/ .
  (In Subversion 1.10, shelves were stored under <WC>/.svn/shelves/ as
  patch files. To recover a shelf created by 1.10, either use a 1.10
  client to find and unshelve it, or find the patch file and use any
  1.10 or later 'svn patch' to apply it.)

  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:
  -q [--quiet]             : print nothing, or only summary information
  --dry-run                : try operation but make no changes
  --keep-local             : keep path in working copy

(...)

$ svn x-unshelve --help
x-unshelve: Copy shelved changes back into the WC.
usage: x-unshelve [--drop] [SHELF [VERSION]]

  Apply the changes stored in SHELF to the working copy.
  SHELF defaults to the newest shelf.

  Apply the newest version of the shelf, by default. If VERSION is
  specified, apply that version and discard all versions newer than that.
  In any case, retain the unshelved version and versions older than that
  (unless --drop is specified).

  With --drop, delete the entire shelf (like 'svn shelf-drop') after
  successfully unshelving with no conflicts.

  The working files involved should be in a clean, unmodified state
  before using this command. To roll back to an older version of the
  shelf, first ensure any current working changes are removed, such as
  by shelving or reverting them, and then unshelve the desired version.

  Unshelve normally refuses to apply any changes if any path involved is
  already modified (or has any other abnormal status) in the WC. With
  --force, it does not check and may error out and/or produce partial or
  unexpected results.

  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:
  --drop                   : drop shelf after successful unshelve
(...)

$ svn help | grep x-
 x-shelf-diff
 x-shelf-drop
 x-shelf-list (x-shelves)
 x-shelf-list-by-paths
 x-shelf-log
 x-shelf-save
 x-shelve
 x-unshelve
17
snipsnipsnip

Je ne sais pas d'un moyen facile de faire cela avec juste svn. Honnêtement, je conseillerais d'utiliser git-svn 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 garder 90% de votre flux de travail git tout en restant en communication avec un serveur svn.

8
Walter Mundt

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

Il fonctionne comme les solutions svn diff/patch Mentionnées et propose de transférer et d'afficher les modifications sous forme de différences dans un répertoire local. Malheureusement, les stash ne peuvent pas être nommés, et seul le dernier peut être affiché (bon, oui, c’est une pile, mais il n’ya aucune raison réelle pour une telle limitation.) Mais alors, vous pouvez toujours intégrer les fonctionnalités manquantes dans le dossier. la source.

Il est écrit pour * ix, mais après avoir remplacé chaque "/" par os.sep, Il fonctionne également sous Windows.

Si vous utilisez la version 1.7 ou une version supérieure de svn, vous devez modifier is_a_current_stash(): supprimer la ligne if ".svn" in os.listdir(CURRENT_DIR):, car il n'y a qu'un seul sous-répertoire .svn de niveau supérieur dans 1,7 WC.

4
cxxl

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

4
lili

une autre option consiste à copier votre commande actuelle dans un nouveau répertoire et à annuler toutes vos modifications. De cette façon, vous évitez les tracas liés à la création d’une branche temporaire sur votre serveur. Après tout, le stashing est une opération locale, que tout le monde ne devrait pas voir et qui peut être fait assez souvent.

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

3
knittl

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

Je n'ai pas trouvé de solution définitive, sauf pour exporter l'arborescence, revenir au référentiel, effectuer mes modifications et valider, puis comparer les modifications de l'arborescence exportée dans mon répertoire contrôlé par le code source à l'aide d'un outil tel que Beyond Compare.

Une autre solution consiste peut-être à passer du répertoire HEAD à un autre répertoire, à apporter vos modifications et à la validation. Une fois que vous êtes prêt à les fusionner avec votre autre copie de travail, effectuez une mise à jour et fusionner vos modifications.

1
Anthony Shaw

Je garde toujours une seconde commande, que j'appelle "trunk_clean". Chaque fois que je dois faire un changement rapide et isolé en rapport avec ce que je fais, je m'engage simplement sur cette commande.

1
angularsen

Puisque Subversion ne supporte pas parfaitement les fonctionnalités de stash,
Je viens de faire de manière manuelle comme ça.

Placez Development et Production(release) projet dans un chemin séparé.

source\code\MyApp         -- Development
release\MyApp(release)    -- Production(release)

Vous pouvez utiliser toutes les nouvelles fonctionnalités de votre projet dans le chemin de développement,
et vous ne feriez que des progrès significatifs ou quelque chose devrait être libéré pour l'écurie.

Lorsque vous devez le publier pour la production, ouvrir le projet de production, mettre à jour svn et créer des éléments à publier (construction, exportation, etc.).

Je sais que cela est un peu gênant, mais la publication de progrès ne se produit pas souvent (cela ne me concerne pas, mais je sais que certains projets le font), comparez pour développer des progrès, cette méthode me convient.

J'utilise svn pour des projets spécifiques, car les membres de l'équipe de projet l'utilisent. Je dois donc suivre.
La meilleure solution consiste à utiliser git qui possède un système de contrôle de version parfait et meilleur que svn.

0
wonsuc

Dans ma pratique, j'utilise git init pour créer un référentiel Git dans le répertoire trunk de mon référentiel Subversion, puis j’ajoute *.git aux enchères ignorent les modèles.

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 avoir validé le dépôt Subversion, j’utilise git stash pop pour restaurer mes modifications.

0
yhluo

Utilisation:

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

Il créera une branche à partir de l'emplacement actuel et de la révision actuelle, puis validera les modifications de la copie de travail dans cette branche sans y basculer.

utilisation: copie SRC [@REV] ... DST

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

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

Notez que les modifications de la copie de travail ne seront pas automatiquement annulées (cp ne fait que CoPying modifications apportées à une nouvelle branche) et vous devez les annuler manuellement.

Pour restaurer les modifications, vous pouvez simplement fusionner les modifications d'une branche nouvellement créée vers votre copie de travail.

svn merge --ignore-ancestry ^/trash-stash/my-stash -c <commited revision>

--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 au chemin caché. Les révisions validées sont également imprimées.

Si vous n'avez plus besoin de la réserve, lancez simplement:

svn rm ^/trash-stash/my-stash

Cette solution est préférable à l’utilisation de correctif, car si de nouvelles modifications de la copie de travail ou de la branche actuelle entrent en conflit avec les modifications de la réserve, vous pouvez les résoudre en utilisant svn signifie, alors que patch échouera simplement dans certains cas. ou même appliquer le correctif de manière incorrecte.

0
anton_rh

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.

0
Raheel

Les idées de branchement et de correction ci-dessus sont excellentes, mais elles ne fonctionnent pas bien pour moi. J'utilise un outil de différenciation visuelle, si bien que l'exécution de git diff Ne produit pas de correctifs textuels. Notre système de génération crée un nouvel environnement chaque fois qu'une branche est créée. La création de branches temporaires "stash" deviendrait donc compliqué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.

0
Ryan DeBeasi