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.
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:
Extraire une nouvelle copie de travail pour la deuxième tâche.
ou
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.
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.)
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).
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.
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
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.
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.
Vous pouvez le faire facilement en utilisant Intellij IDEA - Shelve Changes
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"
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.
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.
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
.
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.
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.
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.
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.