在编写存储在Subversion仓库中的软件时,我经常修改一些文件,然后注意我想为我的主要工作做一些预备性更改。例如。在实现新功能时,我注意到一些可能对我有帮助的重构。
为了不混合两个不相关的更改,在这些情况下,我想“收起”我的更改,即恢复到存储库版本,执行其他一些更改,提交这些更改,然后“取回”我的更改。
git-stash允许这样做。是否有一些方法可以直接或使用某些插件或脚本使用Subversion。 Eclipse插件也没关系。
答案 0 :(得分:320)
This blog post建议使用diff和patch。
git stash
大约变为svn diff > patch_name.patch; svn revert -R .
git stash apply
变为patch -p0 < patch_name.patch
请注意,这不会隐藏元数据更改或(我认为)目录创建/删除。 (是的,与git不同,svn与目录内容分开跟踪它们。)
答案 1 :(得分:171)
您可以使用svn diff
将当前更改存储到修补程序文件中,然后还原您的工作副本:
svn diff > stash.patch
svn revert -R .
在实施预备功能后,您可以使用修补程序实用程序应用修补程序:
patch < stash.patch
正如其他人所说,这不适用于svn:properties
和树操作(添加,删除,重命名文件和目录)。
二进制文件也可能会出现问题,我不知道补丁(或者TortoiseSVN在这种情况下如何处理它们)。
答案 2 :(得分:68)
当我从工作副本中的一个任务获得未提交的更改并且我需要切换到另一个任务时,我会执行以下两项操作之一:
查看第二项任务的新工作副本。
或
开始分支:
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
我有一些脚本可以帮助自动执行此操作。
答案 3 :(得分: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
如果定期进行,可以(也可能应该)放入脚本中。
答案 4 :(得分:15)
从1.10.0(2018-04-13)开始,您有实验svn shelve
command。 (TortoiseSVN supports the command)它只是帮助保存补丁并应用,因此它具有与svn diff
+ patch
相同的限制(即无法处理二进制文件和重命名)。 (修改:Looks like binary support is coming at next version)
编辑^ 2:使用1.11.0(2018-10-30发布),二进制文件为supported。搁置重命名的文件仍然不受支持。 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
答案 5 :(得分:7)
我不知道用svn做一个简单的方法。老实说,我建议使用git-svn
创建一个git repo,它充当svn工作副本,并且只使用git stash
。只需将git pull
替换为git svn rebase
,将git push
替换为git svn dcommit
,您实际上可以保留90%的git工作流,并且仍然可以与svn服务器通信。
答案 6 :(得分:4)
在GPL 3下有一个名为svn-stash
的小型Python 2脚本:https://github.com/frankcortes/svn-stash。
它的工作方式与提到的svn diff/patch
解决方案类似,并提供了更改的推送和弹出作为差异到一些本地目录。不幸的是,stashes无法命名,只有最后一个可以弹出(好吧,是的,它是一个堆栈,但没有真正的理由存在这样的限制。)但是,你可以随时将缺少的功能构建到源。
它是为* ix编写的,但在用os.sep
替换每个“/”之后,它在Windows下也可以很好地工作。
如果您使用svn 1.7或更高版本,则需要更改is_a_current_stash()
:删除行if ".svn" in os.listdir(CURRENT_DIR):
,因为1.7 WC中只有一个顶级.svn子目录。
答案 7 :(得分:4)
您可以使用Intellij IDEA轻松完成 - Shelve Changes
答案 8 :(得分:3)
另一个选项是将当前结帐复制到新目录并还原所有更改。通过这种方式,您可以节省在服务器上创建临时分支的麻烦 - 所有存储都是本地操作,并非每个人都应该看到并且可以经常进行。
提交修补程序后,您可以更新主要工作副本并删除“存储区域”
答案 9 :(得分:1)
我想对上面提到的所有解决方案做一个总结,因为这个问题下太乱了。一些高票答案模棱两可,我花了很多时间来证明答案的某些部分是否正确。
解决方案:
shelve
(见下文)我尝试了 1.
2.
和 3.
。
1.
是最简单和最安全的。如果您想节省时间,请使用此解决方案。我知道不优雅。
3.
不是我的选择,因为:
git stash -u
。4.
shelve
将是最优雅的方式,也是与 git stash -u
最相似的方式。
添加未添加/未跟踪的文件 -> shelve
-> 完成。
看到了吗?与git stash -u
相比,唯一的区别是您必须先添加未添加的文件,然后shelve
。
测试环境:
我正在测试所有使用 Windows Tortoise SVN 客户端、网络共享副本 (SAMBA) 和由 Windows Tortoise SVN 客户端创建的本地存储库的用户。
所以我不知道如果您使用的是与 local share 不同的 SVN 服务器,情况会有什么不同。但我想 shelve
可以在任何情况下工作,因为它是一个本地操作/功能。
答案 10 :(得分:1)
我也想要这个功能。我目前使用TortoiseSVN。
我没有找到一个硬解决方案,除了导出树,还原到存储库进行更改和提交,然后使用Beyond Compare等工具将导出树中的更改反馈回源控制目录。
或者,另一种解决方案可能是从HEAD分支到另一个目录,进行更改和提交。准备好将这些内容合并回其他工作副本后,请执行更新并合并更改。
答案 11 :(得分:1)
我总是保留第二个结账,我称之为“trunk_clean”。每当我需要做一个与我正在做的事情有关的快速,孤立的变化时,我只是提交结账。
答案 12 :(得分:0)
在我的实践中,我使用git init
在我的Subversion存储库的trunk
目录中创建一个Git存储库,然后我将*.git
添加到Suctions忽略模式。
修改一些文件后,如果我想继续使用Subversion主线,我只需使用git stash
来隐藏我的工作。在提交到Subversion存储库后,我使用git stash pop
来恢复我的修改。
答案 13 :(得分:0)
根据Walter的回答,我在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.stash 隐藏更改, svn.stash.apply 应用存储。
答案 14 :(得分:0)
上面的分支和修补方法很棒,但它们对我来说效果不佳。我使用视觉差异工具,因此运行git diff
不会产生基于文本的补丁。每次创建分支时,我们的构建系统都会创建一个新的环境,因此创建临时的&#34; stash&#34;分支会变得混乱。
相反,我写了一个little shell script,将文件复制到&#34; shelf&#34;目录,添加时间戳,并还原更改。它没有上述解决方案那么强大,但它也避免了我遇到的一些陷阱。
答案 15 :(得分:0)
使用:
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
只是 CoPying 更改为新分支),您必须手动还原它们。
要恢复更改,您只需将新创建的分支中的更改合并到工作副本即可。
svn merge --ignore-ancestry ^/trash-stash/my-stash -c <commited revision>
--ignore-ancestry
用于不更新工作副本中的合并信息。
使用:
svn ls -v ^/trash-stash/
查看藏匿路径中的内容。还会打印承诺的修订版。
如果您不再需要藏匿,请运行:
svn rm ^/trash-stash/my-stash
此解决方案优于使用补丁,因为如果工作副本或当前分支上的新更改与存储中的更改冲突,您可以使用svn方法解决冲突,而patch
在某些情况下会只是失败甚至错误地应用补丁。
答案 16 :(得分:0)
由于Subversion不完美支持stash
功能,
我只是这样手动操作。
将Development
和Production(release)
投影到单独的路径。
source\code\MyApp -- Development
release\MyApp(release) -- Production(release)
您可以在开发路径中为项目使用任何新功能,
并且您只会做出有意义的进步,或者应该为稳定版发布一些东西。
当您必须将其发布以进行生产时,请打开生产项目,更新svn并进行发布(构建,导出...等)工作。
我知道这有点麻烦,但是发布进度并不经常发生(这不适合我,但我知道有些项目确实可以)与开发进度相比,这种方式很适合我。
由于项目团队成员使用svn,因此我将其用于特定项目,所以我必须遵循。
最好的解决方案是使用git
,它具有完善的版本控制系统,并且比svn
更好。