在对存储在Subversion版本库中的软件进行编程时,我经常修改一些文件,然后注意我想为我的主要工作做一些准备性的更改。例如,在实现新功能时,我注意到一些重构可能会对我有所帮助。
为了不混淆两个无关的更改,在这种情况下,我想“收藏”我的更改,即还原到存储库版本,进行其他更改,提交这些更改,然后“取回”我的更改。
git-stash可以做到这一点。是否可以通过Subversion直接或使用某些插件或脚本来执行此操作。Eclipse插件也可以。
在对存储在Subversion版本库中的软件进行编程时,我经常修改一些文件,然后注意我想为我的主要工作做一些准备性的更改。例如,在实现新功能时,我注意到一些重构可能会对我有所帮助。
为了不混淆两个无关的更改,在这种情况下,我想“收藏”我的更改,即还原到存储库版本,进行其他更改,提交这些更改,然后“取回”我的更改。
git-stash可以做到这一点。是否可以通过Subversion直接或使用某些插件或脚本来执行此操作。Eclipse插件也可以。
Answers:
当我对工作副本中的一个任务进行了未提交的更改并且需要切换到另一任务时,我将执行以下两项操作之一:
签出第二份工作的新工作副本。
要么
开始分支:
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
我有一些脚本可以帮助实现自动化。
project\temp\<creationdate-reason>
或project\personal\<creationdate-reason>
为此目的。
这篇博客文章建议使用diff和patch。
git stash
大约变成 svn diff > patch_name.patch; svn revert -R .
git stash apply
变成 patch -p0 < patch_name.patch
请注意,这不会存储元数据更改或(我认为)目录创建/删除。(是的,与git不同,svn与目录内容分开地跟踪它们。)
svn patch patch_name.patch
而不是,则可以或多或少地跟踪元数据patch -p0
,因为它们位于修补程序文件中,并且svn patch可以理解它们。
您可以将当前的更改存储svn diff
到补丁文件中,然后还原工作副本:
svn diff > stash.patch
svn revert -R .
实施准备功能后,可以使用补丁实用程序应用补丁:
patch < stash.patch
正如其他人指出的那样,这不适用于svn:properties
和树操作(添加,删除,重命名文件和目录)。
二进制文件也可能带来问题,我不知道修补程序(或在这种情况下为TortoiseSVN)如何处理它们。
$ patch --strip=0 < stash.patch
这将确保在应用补丁时,补丁不会询问您文件名。
最简单的方法是使用临时分支,如下所示:
$ 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
如果更定期地将其放在脚本中,可能应该放进脚本中。
从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和1.14.0周围没有变化。命令仍被标记为实验性命令,您需要定义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
我不知道仅用svn就能做到的简单方法。老实说,我建议使用git-svn
制作一个git repo来作为svn工作副本,并仅使用git stash
它。只需替换为git pull
with git svn rebase
和git push
,git svn dcommit
您实际上就可以保留90%的git工作流程,并且仍在与svn服务器通信。
svn-stash
在GPL 3下有一个称为Python 2的小脚本: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子目录。
另一个选择是将您当前的结帐复制到新目录并还原所有更改。这样,您将省去在服务器上创建临时分支的麻烦-毕竟所有存储都是本地操作,不是每个人都应该看到的,并且可以经常执行。
提交修补程序后,您可以更新主工作副本并删除“存储区”
根据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可以应用存储。
在我的实践中,我通常在Subversion存储git init
库的trunk
目录中创建一个Git存储库,然后将其添加*.git
到Suctions忽略模式中。
修改了一些文件后,如果我想继续使用Subversion主线工作,我只是git stash
用来存放我的工作。提交到Subversion存储库后,我用于git stash pop
还原修改。
采用:
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
在某些情况下甚至会失败甚至不正确地应用修补程序。
由于Subversion并不stash
完美地支持功能,因此
我只是这样做。
放置Development
并Production(release)
投影到单独的路径。
source\code\MyApp -- Development
release\MyApp(release) -- Production(release)
您可以在开发路径中为项目使用任何新功能,
并且您只会提交有意义的进度,或者应该发布一些稳定的东西。
当您必须将其发布以进行生产时,请打开生产项目,更新svn并进行发布(构建,导出等)工作。
我知道这有点麻烦,但是发布进度并不经常发生(这对我来说不行,但我知道有些项目确实如此)与开发进度相比,这种方式很适合我。
由于项目团队成员使用svn,因此我将其用于特定项目,因此我必须遵循。
最好的解决方案是使用git
具有完善的版本控制系统并且优于的版本svn
。
dev
和prod
,2种情况。要开发全新的功能,使用svn将会很复杂。我不确定在svn世界中是否有解决您案件的明确方法。