当对存储在Subversion repo中的软件进行编程时,我经常修改一些文件,然后注意到我想对我的主要工作做一些准备性更改。例如,在实现新功能时,我注意到一些重构可能会对我有所帮助。

为了不将两个不相关的更改混合在一起,在这种情况下,我想“收起”我的更改,即恢复到存储库版本,做一些其他更改,提交这些更改,然后“取回”我的更改。

Git-stash允许这样做。有没有办法在Subversion中直接或通过一些插件或脚本来做到这一点?Eclipse插件也可以。


当前回答

这篇博文建议使用diff和patch。

Git stash大约变成SVN diff > patch_name.patch;svn revert -R。 Git stash应用变成补丁-p0 < patch_name.patch

注意,这不会隐藏元数据更改或(我认为)目录创建/删除。(是的,svn与目录内容分开跟踪,不像git。)

其他回答

我也想要这个功能。我目前使用的是TortoiseSVN。

除了导出树,还原到存储库进行更改并提交,然后使用Beyond compare之类的工具将导出树中的更改比较回源代码控制目录之外,我还没有找到一个可靠的解决方案。

或者,另一种解决方案可能是从HEAD分支到另一个目录,进行更改并提交。一旦准备好将这些内容合并回其他工作副本,就可以进行更新并合并更改。

从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中的货架与早期版本创建的货架不兼容。

编辑^4:1.13.0(2019年10月)和1.14.0(2020年5月)的搁置没有变化。命令仍被标记为实验性,需要定义SVN_EXPERIMENTAL_COMMANDS=shelf3才能启用该特性。看起来这个功能目前还没有分类。

设计说明可以在开发者的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

上面的分支和补丁想法很棒,但对我来说并不管用。我使用一个可视化的diff工具,所以运行git diff不会产生基于文本的补丁。每次创建分支时,我们的构建系统都会旋转一个新环境,因此创建临时的“隐藏”分支会很混乱。

相反,我编写了一个小shell脚本,它将文件复制到“shelf”目录,添加时间戳,并恢复更改。它不如上面的解决方案健壮,但它也避免了我遇到的一些陷阱。

Use:

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

它将从当前位置和当前修订创建一个分支,然后将工作副本中的更改提交给该分支,而不切换到该分支。

复制SRC[@REV]…DST SRC和DST都可以是工作副本(WC)路径或URL: WC -> URL:立即将WC副本提交到URL

注意,工作副本中的更改不会自动恢复(cp只是将更改复制到一个新的分支),您必须手动恢复它们。

要恢复更改,只需将新创建的分支的更改合并到工作副本。

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

——ignore-ancestry用于不更新工作副本中的合并信息。

Use:

svn ls -v ^/trash-stash/

看看你藏东西的地方有什么。提交的修订版也被印刷。

如果你不需要了,就运行:

svn rm ^/trash-stash/my-stash

这种解决方案比使用patch更好,因为如果工作副本或当前分支的新更改与stash中的更改发生冲突,可以使用svn手段解决冲突,而patch在某些情况下会失败甚至不正确地应用patch。

由于Subversion不完全支持存储特性, 我就像这样手动操作。

将开发和生产(发布)项目放在一个分开的路径上。

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

你可以在开发过程中为你的项目添加任何新功能, 你只会承诺有意义的进展,或者应该为稳定释放一些东西。

当你必须将它发布到生产环境,开放生产项目,更新svn并做一些事情来发布(构建,导出…)等等)。

我知道这有点麻烦,但与开发进度相比,发布进度并不经常发生(对我来说不是这样,但我知道有些项目是这样),这种方式适合我。

由于项目组成员使用svn,所以具体项目我使用svn,所以我必须遵循。 最好的解决方案是使用git,它有完善的版本控制系统,比svn更好。