subversion - svn vs git
Guarde temporalmente los cambios no confirmados en Subversion(a la "git-stash") (15)
A partir de 2018-04-13 (Subversion 1.10.0), tiene el comando experimental svn shelve
. ( TortoiseSVN soporta el comando )
A partir de la 1.10.0, no es más que un ayudante para guardar un parche y aplicar de nuevo, por lo que tiene las mismas limitaciones que svn diff
+ patch
(es decir, no puede manejar archivos binarios y cambiar el nombre). ( Editar : Parece que el soporte binario viene en la próxima versión )
Edición ^ 2: con 1.11.0 (publicado 2018-10-30), los archivos binarios son supported . Los archivos con renombrado de estanterías permanecieron sin soporte. Estanterías en 1.11 es incompatible con las estanterías creadas por 1.10.
Las notas de diseño se pueden encontrar en su 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
Mientras programo el software almacenado en un repositorio de Subversion, a menudo modifico algunos archivos, luego me doy cuenta de que me gustaría hacer algún cambio preparatorio para mi trabajo principal. Por ejemplo, al implementar una nueva funcionalidad, observo algunas refactorizaciones que podrían ayudarme.
Para no mezclar dos cambios no relacionados, en estos casos me gustaría "guardar" mis cambios, es decir, volver a la versión del repositorio, hacer algunos otros cambios, confirmarlos y luego "recuperarlos".
git-stash permite hacer precisamente eso. ¿Hay alguna manera de hacer esto con Subversion, ya sea directamente o con algún complemento o script. Los complementos de Eclipse también estarían bien.
Basándome en la respuesta de Walter, he creado los siguientes alias en mi archivo 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''
Estos alias son mucho más fáciles de usar y recordar.
Uso:
svn.stash para esconder cambios y svn.stash.apply para aplicar stash.
Cuando tengo cambios no confirmados de una tarea en mi copia de trabajo y necesito cambiar a otra tarea, hago una de dos cosas:
Echa un vistazo a una nueva copia de trabajo para la segunda tarea.
o
Iniciar una rama:
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
Tengo algunos scripts que ayudan a automatizar esto.
En mi práctica, uso git init
para crear un repositorio Git en el directorio trunk
de mi repositorio Subversion, y luego agrego *.git
a los patrones de succión que ignoran.
Después de modificar algunos archivos, si quiero continuar mi trabajo con la línea principal de Subversion, solo uso git stash
para esconder mi trabajo. Después de comprometerme con el repositorio de Subversion, uso git stash pop
para restaurar mis modificaciones.
Hay un pequeño script de Python 2 llamado svn-stash
disponible en GPL 3: https://github.com/frankcortes/svn-stash .
Funciona como las soluciones de svn diff/patch
mencionadas y ofrece cambios y cambios en los directorios locales. Desafortunadamente, no se pueden nombrar los escondites, y solo se puede abrir el último (bueno, sí, es una pila, pero no hay una razón real para tal limitación). Pero entonces, siempre se podrían incluir las características que faltan en el fuente.
Está escrito para * ix, pero después de reemplazar cada "/" con os.sep
también funciona bien en Windows.
Si usa svn 1.7 o superior, necesita cambiar is_a_current_stash()
: elimine la línea if ".svn" in os.listdir(CURRENT_DIR):
ya que solo hay un subdirectorio de nivel superior .svn en 1.7 WC.
La forma más fácil sería usar una rama temporal, como esta:
$ 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
Esto podría (y probablemente debería) ser puesto en un script si se hace de forma más regular.
Las ideas de ramificación y parcheo anteriores son excelentes, pero no funcionan bien para mí. Utilizo una herramienta visual diff, por lo que ejecutar git diff
no produce parches basados en texto. Nuestro sistema de compilación crea un nuevo entorno cada vez que se crea una rama, por lo que la creación de ramas "ocultas" temporales podría causar problemas.
En su lugar, escribí un pequeño script de shell que copia un archivo a un directorio de "estantería", agrega una marca de tiempo y revierte el cambio. No es tan robusto como las soluciones anteriores, pero también evita algunas de las trampas con las que me encontré.
No conozco una forma fácil de hacer eso con solo svn. Honestamente, recomendaría usar git-svn
para hacer un repositorio de git que actúe como una copia de trabajo svn, y solo usar git stash
con eso. Simplemente reemplace git pull
con git svn rebase
y git push
con git svn dcommit
y realmente puede mantener el 90% de su flujo de trabajo de git y seguir hablando con un servidor svn.
Puede almacenar sus cambios actuales con svn diff
en un archivo de parche, y luego revertir su copia de trabajo:
svn diff > stash.patch
svn revert -R .
Una vez que haya implementado su función de preparación, puede aplicar su parche con la utilidad de parche:
patch < stash.patch
Como han dicho otros, esto no funcionará con svn:properties
y operaciones de árbol (agregar, eliminar, renombrar archivos y directorios).
Los archivos binarios también pueden dar problemas, no sé cómo los parches (o TortoiseSVN en este caso los maneja).
Puedes hacerlo fácilmente usando Intellij IDEA - Shelve Changes
Siempre mantengo una segunda verificación, que llamo "trunk_clean". Cada vez que necesito hacer un cambio rápido y aislado relacionado con lo que estoy haciendo, simplemente me comprometo en ese pago.
También he querido esta característica. Actualmente uso TortoiseSVN.
No he encontrado una solución rígida, excepto para exportar el árbol, volver al repositorio, realizar mis cambios y confirmar, luego comparar los cambios del árbol exportado en mi directorio controlado de origen usando una herramienta como Beyond Compare.
O, otra solución podría ser pasar de HEAD a otro directorio, hacer los cambios y confirmar. Una vez que esté listo para fusionarlos con su otra copia de trabajo, haga una actualización y combine sus cambios.
Utilizar:
svn cp --parents . ^/trash-stash/my-stash
Creará una sucursal a partir de la ubicación actual y la revisión actual, y luego confirmará los cambios en la copia de trabajo de esa sucursal sin tener que cambiarla.
uso: copiar SRC [@REV] ... DST
SRC y DST pueden ser una ruta de copia de trabajo (WC) o URL:
WC -> URL: immediately commit a copy of WC to URL
Tenga en cuenta que los cambios en la copia de trabajo no se revertirán automáticamente ( cp
es solo hacer cambios en una nueva rama) y que debe revertirlos manualmente.
Para restaurar los cambios, puede simplemente fusionar los cambios de la rama recién creada a su copia de trabajo.
svn merge --ignore-ancestry ^/trash-stash/my-stash -c <commited revision>
--ignore-ancestry
se utiliza para no actualizar la información de fusión en la copia de trabajo.
Utilizar:
svn ls -v ^/trash-stash/
Para ver lo que tienes en el camino del alijo. Revisiones comprometidas también se imprimen.
Si ya no necesita el alijo, simplemente ejecute:
svn rm ^/trash-stash/my-stash
Esta solución es mejor que usar el parche, ya que si los nuevos cambios en la copia de trabajo o en la rama actual entran en conflicto con los cambios en el alijo, puede resolver los conflictos usando svn significa, mientras que el patch
en algunos casos simplemente fallará o incluso aplicará el parche de manera incorrecta .
otra opción es copiar su pago actual a un nuevo directorio y revertir todos sus cambios. De esta manera, ahorrará la molestia de crear una rama temporal en su servidor; después de todo, el ocultamiento es una operación local, que no todos deberían ver y se puede hacer con bastante frecuencia.
después de confirmar su revisión, puede actualizar su copia de trabajo principal y eliminar su "área de almacenamiento"
Esta entrada de blog aconseja el uso de diff y parche.
-
git stash
aproximadamente se convierte ensvn diff > patch_name.patch; svn revert -R .
svn diff > patch_name.patch; svn revert -R .
-
git stash apply
convierte enpatch -p0 < patch_name.patch
Tenga en cuenta que esto no oculta los cambios de metadatos o (creo) que el directorio crea / elimina. (Sí, svn realiza un seguimiento de estos por separado del contenido del directorio, a diferencia de git).