暂时放弃Subversion中未提交的更改(la"git-stash")

sle*_*ske 305 svn versioning

在编写存储在Subversion仓库中的软件时,我经常修改一些文件,然后注意我想为我的主要工作做一些预备性更改.例如,在实现新功能时,我注意到一些可能对我有帮助的重构.

为了不混合两个不相关的更改,在这些情况下,我想"收起"我的更改,即恢复到存储库版本,执行一些其他更改,提交这些更改,然后"获取"我的更改.

git-stash允许这样做.是否有一些方法可以直接或使用某些插件或脚本使用Subversion.Eclipse插件也没关系.

Wal*_*ndt 327

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

  • git stash 差不多了 svn diff > patch_name.patch; svn revert -R .
  • git stash applypatch -p0 < patch_name.patch

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

  • 这是http://stackoverflow.com/questions/1554278/temporarily-put-away-uncommited-changes-in-subversion-a-la-git-stash/1554343#1554343的偶然重复 - 在那里发送upvotes. (13认同)
  • 如果你使用`svn patch patch_name.patch`而不是`patch -p0`,你可以或多或少地跟踪元数据,因为它们在补丁文件中,并且svn补丁理解它们. (6认同)
  • 它似乎也不包含二进制文件,这很烦人.至少在使用TortoiseSVN生成补丁时. (2认同)

kni*_*ttl 175

您可以将当前更改存储svn diff到修补程序文件中,然后还原工作副本:

svn diff > stash.patch
svn revert -R .
Run Code Online (Sandbox Code Playgroud)

在实现预备功能之后,您可以使用修补程序实用程序应用修补程序:

patch < stash.patch
Run Code Online (Sandbox Code Playgroud)

正如其他人已经注意到这将无法使用svn:properties树操作(添加,删除,重命名文件和目录).

二进制文件也可能会出现问题,我不知道补丁(或者TortoiseSVN在这种情况下如何处理它们).

  • 请参阅标题为"为什么不使用补丁?"的方框.在http://svnbook.red-bean.com/en/1.5/svn-book.html#svn.branchemerge.basicmerging.stayinsync上了解为什么这是一个坏主意. (7认同)
  • 我认为这对于删除/重命名的文件可能效果不佳. (4认同)
  • @sbi:我认为这不是一个有效的理由.这不是一个"糟糕的答案".这不是完美的答案.我不认为这个人应该受到惩罚他的建议.你宁愿他不回答吗?如果是,那么是的,你应该downvote.否则这是惩罚良好的意图. (4认同)
  • 万一其他人,像我一样,认为这看起来像最轻量级的解决方案,并决定尝试它,我不得不使用补丁-p0 <stash.patch - 否则它抱怨无法找到要补丁的文件 (4认同)
  • @ssg:我投票支持它,因为,你可能认为树木变化(重构任何人?)和属性变化(`svn:ignore`)很少见,失去任何变化的机会不是我觉得冒险的事情,而其他两种可能性(并行结账和临时分支)正在等待使用.当然,不知道为什么其他人会投票,但我想失败的变化并不是很多开发人员所看到的.毕竟,_Not_失去任何变化都是VCS的意思. (3认同)
  • 如果您来自git背景并且由于各种原因被迫使用SVN,这个建议会有所帮助.对于补丁的首次使用者已经给出的建议略有改进:`$ patch --strip = 0 <stash.patch`这将确保补丁在您应用补丁时不会询问您的文件名. (3认同)
  • 我查看了文档,它只阻止补丁,因为 1) svn:props 没有比较 2) 树操作(目录添加等)没有比较。由于两者都很罕见,我认为这种方法仍然是完全可以接受的。我很难理解对此答案的否决背后的心理。 (2认同)

ben*_*din 67

当我从工作副本中的一个任务获得未提交的更改并且我需要切换到另一个任务时,我会执行以下两项操作之一:

  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
    
    Run Code Online (Sandbox Code Playgroud)

我有一些脚本可以帮助自动执行此操作.

  • 这将导致您的subversion服务器上有大量垃圾 (63认同)
  • 不,它不会导致"大量垃圾",除非你是一个完整的邋.. 这种"存储分支"所需的存储量与*更改*提交的大小成比例.此外,您可以在它过时时再次删除分支,这样就不会使分支目录混乱.是的,这是一个像git这样的分布式系统真的获胜的情况,如果OP以不同方式表达他的问题,我会回答:"已经使用git",但他没有. (61认同)
  • 仍然不幸的是,必须在服务器上创建分支.并不是说这些分支会复制大量数据,而是它们创建了很多不必要的引用,就像git这样的系统没有. (11认同)
  • 这对大型存储库没有用.这绝对不是我工作环境中的一个选项.虽然我希望我们的存储库更小,组织更好,坦率地说,是一个git存储库而不是svn,但我只局限于我们的组织中代码的组织方式. (8认同)
  • @ knittl:不,它不会.更重要的是:它不会像您的建议那样导致更改丢失.这个,并且有另一个检查后备箱/同一分支的副本,是我知道的唯一两种可靠的方法.如果您对此感到不舒服,请查看另一份副本并同时处理它. (3认同)
  • @knittl:可以在项目默认分支或标记位置之外的不显眼路径中创建分支.例如,团队可以为此目的指定`project\temp\<creationdate-reason>或`project\personal\<creationdate-reason>`. (2认同)

Jes*_*erE 42

最简单的方法是使用临时分支,如下所示:

$ 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
Run Code Online (Sandbox Code Playgroud)

如果更经常地进行,这可以(并且可能应该)放在脚本中.

  • 很好地使用^语法用于repo root(因为svn 1.6).当你的repo在顶层有trunk/tags/branches时,这是一个很好的解决方案. (5认同)
  • @sleske:SVN不是分布式VCS,所以一切都必须在服务器上.就是那样子. (5认同)
  • 我真的不喜欢把所有这些临时分支放在服务器上.我觉得这应该在本地完成,而不是使服务器混乱(如果你在签到时生成邮件,则生成spurios签入电子邮件).仍然是一个值得记住的选择. (4认同)
  • @sleske:是的,您将临时存储提交到服务器,但分支本身已被删除.无论如何,我认为这是最快,最强大的方法. (3认同)
  • 为什么这个被投票失败,而"解决方案"被投票,甚至在您删除/添加文件或更改任何属性时都不起作用?是的,当你第一次这样做时,这不是最简单的事情,但是,除了检查另一个副本并行工作之外,这是唯一适用于所有情况的解决方案. (2认同)

sni*_*nip 21

从1.10.0(2018-04-13)开始,您有实验svn shelve命令.(TortoiseSVN支持命令)它只是保存补丁和应用的辅助工具,因此它具有与svn diff+ 相同的限制patch(即无法处理二进制文件和重命名).(编辑:看起来二进制支持即将发布到下一版本)

编辑^ 2: 使用1.11.0(2018-10-30发布),支持二进制文件.搁置重命名的文件仍然不受支持.1.11中的搁架与1.10创建的搁板不兼容.

设计说明可以在他们的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
Run Code Online (Sandbox Code Playgroud)


Wal*_*ndt 8

我不知道用svn做一个简单的方法.老实说,我建议使用git-svngit repo作为svn工作副本,并使用git stash它.只需更换git pullgit svn rebasegit pushgit svn dcommit实际上,你可以保持90%的git的工作流程,但仍然可以说话的SVN服务器.