Временно уберите незафиксированные изменения в Subversion (a la " git-stash")



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



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



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

818   15  

15 ответов:

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

  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
    

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

этот блог советует использовать diff и патч.

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

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

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

svn diff > stash.patch
svn revert -R .

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

patch < stash.patch

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

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

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

$ 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

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

по состоянию на 2018-04-13 (Subversion 1.10.0), у вас есть экспериментальные svn shelve команда. (TortoiseSVN поддерживает команду)

В настоящее время это не что иное, как помощник, чтобы сохранить патч и применить его обратно, поэтому он имеет те же ограничения, что и svn diff + patch (т. е. не может обрабатывать двоичные файлы и переименовывает). (Edit:похоже, что поддержка двоичных файлов идет в следующей версии)

$ 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 <WC>/.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
(...)

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

есть небольшой скрипт 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):, так как есть только один верхний уровень .svn subdir в 1.7 WC.

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

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

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

Я также хотел эту функцию. В настоящее время я использую TortoiseSVN.

Я не нашел жесткого решения, кроме как экспортировать дерево, вернуться в репозиторий внести свои изменения и зафиксировать, а затем сравнить изменения из экспортированного дерева обратно в мой каталог с исходным кодом, используя инструмент, подобный Beyond Compare.

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

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

ветвления и исправления идеи выше велики, но они не работают хорошо для меня. Я использую визуальный инструмент diff, так что работает git diff не создает текстовые патчи. Наша система сборки раскручивает новую среду каждый раз, когда создается ветка, поэтому создание временных ветвей "тайника" будет беспорядочным.

вместо этого, я написал маленький shell-скрипт, который копирует файл в каталог "полки", добавляет метку времени, и отменяет изменения. Это не так надежно, как решения выше, но это также позволяет избежать некоторых ловушек, с которыми я столкнулся.

на основе ответа Уолтера я создал следующие псевдонимы в моем файле 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'

эти псевдонимы гораздо проще использовать и запоминать.

использование:

svn.тайник, чтобы спрятать изменения и svn.припрятывать.применить применить заначку.

использование:

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

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

использование: копирование SRC[@REV]... DST

SRC и DST могут быть либо рабочей копией (WC) путь или URL:

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

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

чтобы восстановить изменения, вы можете просто объединить изменения из вновь созданной ветви в рабочую копию.

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

--ignore-ancestry используется для того, чтобы не обновлять информацию о слиянии в рабочей копии.

использование:

svn ls -v ^/trash-stash/

чтобы увидеть, что у вас есть в stash path. Зафиксированные изменения также печатаются.

Если вам больше не нужен тайник, просто запустите:

svn rm ^/trash-stash/my-stash

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

в моей практике я использую git init создать репозиторий Git в trunk каталог моего репозитория Subversion, а затем я добавляю *.git для отсосов игнорировать шаблоны.

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

Comments

    Ничего не найдено.