Временно отложите незафиксированные изменения в Subversion (а-ля "git-stash") - PullRequest
299 голосов
/ 12 октября 2009

При программировании программного обеспечения, хранящегося в репозитории Subversion, я часто изменяю некоторые файлы, а затем замечаю, что хотел бы внести некоторые подготовительные изменения в основную работу. Например. при реализации новых функций я замечаю некоторый рефакторинг, который может мне помочь.

Чтобы не смешивать два несвязанных изменения, в этих случаях я хотел бы «убрать» мои изменения, то есть вернуться к версии репозитория, сделать некоторые другие изменения, зафиксировать их, а затем «извлечь» мои изменения.

git-stash позволяет это сделать. Есть ли способ сделать это с помощью Subversion, напрямую или с помощью какого-либо плагина или скрипта. Плагины Eclipse тоже подойдут.

Ответы [ 16 ]

321 голосов
/ 02 августа 2010

В этом блоге рекомендуется использовать diff и patch.

  • git stash приблизительно становится svn diff > patch_name.patch; svn revert -R .
  • git stash apply становится patch -p0 < patch_name.patch

Обратите внимание, что это не хранит изменения метаданных или (я думаю) каталог создает / удаляет. (Да, svn отслеживает их отдельно от содержимого каталога, в отличие от git.)

172 голосов
/ 12 октября 2009

Вы можете сохранить текущие изменения с помощью svn diff в файле патча, а затем вернуть рабочую копию:

svn diff > stash.patch
svn revert -R .

После того, как вы реализовали свою подготовительную функцию, вы можете применить свой патч с помощью утилиты патча:

patch < stash.patch

Как уже отмечали другие, это не будет работать с svn:properties и операциями с деревьями (добавление, удаление, переименование файлов и каталогов).

Двоичные файлы также могут вызывать проблемы, я не знаю, как исправление (или TortoiseSVN в этом случае их обрабатывает).

68 голосов
/ 12 октября 2009

Когда я получил незафиксированные изменения от одной задачи в моей рабочей копии, и мне нужно переключиться на другую задачу, я делаю одну из двух вещей:

  1. Получите новую рабочую копию для второго задания.

    или

  2. Начать ветку:

    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
    

У меня есть несколько скриптов, которые помогают автоматизировать это.

42 голосов
/ 12 октября 2009

Самый простой способ - использовать временную ветку, например:

$ 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

Это можно (и, вероятно, следует) поместить в сценарий, если это делается на более регулярной основе.

17 голосов
/ 18 апреля 2018

По состоянию на 1.10.0 (2018-04-13) у вас есть экспериментальная svn shelve команда . ( TortoiseSVN поддерживает команду ). Это всего лишь помощник для сохранения патча и применения обратно, поэтому он имеет те же ограничения, что и svn diff + patch (т. Е. Не может обрабатывать двоичные файлы и переименовывать). ( Редактировать : Похоже, бинарная поддержка будет в следующей версии 1.11.0 )

Редактировать ^ 2: С 1.11.0 (выпущен 2018-10-30), двоичные файлы поддерживаются . Переставленные переименованные файлы остались без поддержки. Стеллажи в 1.11 несовместимы с полками, созданными в 1.10.

Редактировать ^ 3: С 1.12.0 (выпущено в 2019-04-24), копирование и переименование поддерживаются . Стеллажи в версии 1.12 несовместимы с полками, созданными в предыдущих версиях.

Примечания по дизайну можно найти на 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
7 голосов
/ 02 августа 2010

Я не знаю простого способа сделать это с помощью SVN. Честно говоря, я бы посоветовал использовать git-svn для создания git-репо, работающего как svn-рабочую копию, и просто использовать git stash с этим. Просто замените git pull на git svn rebase и git push на git svn dcommit, и вы на самом деле можете сохранить 90% рабочего процесса git и по-прежнему общаться с сервером SVN.

4 голосов
/ 02 июня 2016

Вы можете сделать это легко, используя Intellij IDEA - Изменение полки

4 голосов
/ 14 июня 2013

Существует небольшой скрипт Python 2 под названием svn-stash, доступный под лицензией GPL 3: https://github.com/frankcortes/svn-stash.

Он работает как упомянутые решения svn diff/patch и предлагает отправку и извлечение изменений в виде различий в некоторый локальный каталог. К сожалению, тайники не могут быть названы, и может быть выдан только последний (ну, да, это стек, но нет реальной причины для такого ограничения.) Но тогда вы всегда можете встроить отсутствующие функции в источник.

Он написан для * ix, но после замены каждого "/" на os.sep он прекрасно работает и под Windows.

Если вы используете SVN 1.7 или выше, вам нужно изменить is_a_current_stash(): уберите строку if ".svn" in os.listdir(CURRENT_DIR):, поскольку в 1.7 WC есть только один поддиректорий верхнего уровня .svn.

3 голосов
/ 12 октября 2009

другой вариант - скопировать текущую кассу в новый каталог и отменить все ваши изменения. таким образом вы избавите себя от необходимости создавать временную ветвь на своем сервере - ведь сохранение - это локальная операция, которую не все должны видеть, и ее можно делать довольно часто.

после исправления вы можете обновить основную рабочую копию и удалить «область хранения»

1 голос
/ 12 июля 2013

Я всегда держу вторую проверку, которую я называю "trunk_clean". Всякий раз, когда мне нужно сделать быстрое, изолированное изменение, связанное с тем, что я делаю, я просто вместо этого фиксирую эту проверку.

...