使用svn开发项目时,有时由于某种原因,我们不能及时地向svn上提交东西。
为了防止本地机器硬盘挂掉使这些修改丢掉或者想记录某个时间点的修改,我们有必要对这些修改(Modify,Add状态)进行额外的备份。
下面通过组合几个工具,写了个bat脚本来简化这个过程。整个工具包从这里下载:svnModifyBackup
@echo off
set SVN_DEV_PATH="..\.."
set PRE_TEXTOR=".\PreTextor.exe"
set BAK_FOLDER=".\Backup"
set RAR_PATH=".\Rar.exe"svn status %SVN_DEV_PATH% | findstr "^M" > code.lst
svn status %SVN_DEV_PATH% | findstr "^A" >> code.lst
%PRE_TEXTOR% code.lst
md %BAK_FOLDER%
%RAR_PATH% a -agYYYY-MM-DD_HH-MM-SS %BAK_FOLDER%\src @code.lst
pause
这段脚本中包含一个PreTextor.exe(自己写的一个命令行小工具),是用来将svn输出的code.lst内容,修改为rar.exe需要的文件列表
安装TortoiseSVN时,也装上相应的命令行工具(默认会添加svn路径添加到PATH)
rar.exe为WinRar的命令行工具(详细用法可通过rar.exe /?来查看)
特性:
1. rar压缩包名的后缀为当前备份的时间(到秒),防止相互覆盖,如下图所示:
2. 生成rar压缩包会保留文件的目录结构(解压后,方便使用Beyond Compare等比对工具合并修改)
++++++++++++++++++++++++++++++++++++
TortoiseSVN为封装svn命令行的GUI工具,在其About对话框中,有其版本号与svn版本号说明,如下图:
TortoiseProc.exe /command:about // 弹出About对话框
TortoiseProc.exe /command:update /path:"G:\svn\TGameClient" // 打开TortoiseProc.exe并开始更新G:\svn\TGameClient目录到最新
TortoiseProc.exe /command:update /rev:22895 /path:"G:\svn\TGameClient" // 打开TortoiseProc.exe并开始更新G:\svn\TGameClient目录到22895版本
TortoiseProc.exe /command:update /ignoreexternals /path:"G:\svn\TGameClient" // 打开TortoiseProc.exe并开始忽略所有externals更新G:\svn\TGameClient目录到最新
TortoiseProc.exe /command:commit /path:"G:\svn\TGameClient" // 打开TortoiseProc.exe并显示G:\svn\TGameClient目录下提交对话框
TortoiseProc.exe /command:log /path:"G:\svn\TGameClient" // 打开TortoiseProc.exe并显示G:\svn\TGameClient目录的日志对话框
TortoiseProc.exe /command:log /path:"G:\svn\toys.upk" // 打开TortoiseProc.exe并显示G:\svn\toys.upk文件的日志对话框
更多TortoiseSVN命令详见:https://tortoisesvn.net/docs/nightly/TortoiseSVN_zh_CN/tsvn-automation.html
++++++++++++++++++++++++++++++++++++
svn常用命令:
svn --help // 查看svn命令帮助
svn info --help // 查看svn info命令帮助
svn info TRUNK_URL // 获取TRUNK_URL库的最新信息,如当前版本号
svn info // 获取当前目录的本地信息,如TRUNK_URL路径、本地当前svn版本号
svn info main.c // 获取当前目录下main.c的本地版本信息,如TRUNK_URL路径、本地当前svn版本号
svn list // 查看当前服务器下该目录文件信息
svn list -v // 详细模式查看当前服务器下该目录文件信息
svn list -v -R // 详细模式查看当前服务器下该目录(递归子目录)文件信息
svn auth // 查看所有svn凭据
注1:第一次拉取版本时,会弹出Authentication框,要求输入用户名和密码
注2:在win7下,svn凭据都保存在%homepath%\AppData\Roaming\Subversion\auth
注3:可通过TortoiseSVN Password Decrypter(网页)读取得到凭据中密码
注4:可在TortoiseSVN的Settings -- Saved Data中点击Clear、Clear all按钮清除掉凭据,这样在执行svn操作时会再次弹出Authentication框,要求输入用户名和密码
svn copy TRUNK_URL BRANCH_URL –m "Create branch from trunk 1665" // 从TRUNK_URL的基线号1665,创建一个分支到BRANCH_URL
svn co TRUNK_URL // 将TRUNK_URL最新版本检出到当前目录
svn co TRUNK_URL --ignore-externals // 将TRUNK_URL(忽略external外链)最新版本检出到当前目录
svn co --username chen --password test --no-auth-cache TRUNK_URL // 使用用户名为chen密码为test的账号(不缓存该用户信息)将TRUNK_URL最新版本检出到当前目录
svn co TRUNK_URL@1665 PATH --force // 将TRUNK_URL的基线号1665版本检出到PATH路径下(若PATH路径存在则强制覆盖)
svn export TRUNK_URL // 将TRUNK_URL最新版本导出到当前目录
svn export --username chen --password test --no-auth-cache TRUNK_URL // 使用用户名为chen密码为test的账号(不缓存该用户信息)将TRUNK_URL最新版本导出到当前目录
svn export TRUNK_URL@1665 PATH --force // 将TRUNK_URL的基线号1665版本导出到PATH路径下(若PATH路径存在则强制覆盖)
svn sw BRANCH_URL // 将当前svn切到BRANCH_URL分支
svn sw --username chen --password test --no-auth-cache BRANCH_URL // 使用用户名为chen密码为test的账号(不缓存该用户信息)将当前svn切到BRANCH_URL分支
svn ci –m "comments" // 提交当前目录内的修改(递归子目录)到svn
svn ci –m "comments" d:\TestDir // 提交d:\TestDir目录内的修改(递归子目录)到svn
svn ci –m "comments" d:\TestDir\Game.exe // 提交d:\TestDir\Game.exe到svn
svn ci –m "comments" d:\TestDir\Game.exe e:\scripts\* // 提交d:\TestDir\Game.exe和e:\scripts目录下的所有文件到svn
svn add d:\TestDir // 将d:\TestDir所有目录和文件(递归,除非文件后缀在svn::ignore中)添加本地add状态
svn add abc\Test\123.txt --force --parents // 将当前目录下的abc\Test\123.txt文件及所有父目录添加本地add状态
svn merge TRUNK_URL d:\branch0223 // 将主干最近的改动合并到分支d:\branch0223 注:--merge_to=20210612_svn_218439_715Version
svn merge -c 1665 TRUNK_URL d:\branch0223 // 将主干1665改动合并到分支d:\branch0223
svn merge -c 1665 TRUNK_URL\test.txt d:\branch0223\test.txt // 将主干的test.txt文件的1665改动合并到d:\branch0223下的test.txt中
svn merge -r 1665:2015 TRUNK_URL d:\branch0223 // 将主干(1665,2015]改动合并到分支d:\branch0223
-----------------------------------------------------
合并成功后,可以使用一下日志格式和内容进行提交
Merged revision(s) 1665:2015 from game_proj/trunk/MyGame/Src:
半灵状态加个时间显示
........
-----------------------------------------------------
svn --reintegrate merge BRANCH_URL d:\trunk // 将分支的改动合并到主干d:\trunk
svn merge -r 801897:801046 d:\TestDir\Game.exe // d:\TestDir\Game.exe从当前801897版本回退到801046版本
svn mergeinfo http://tc-svn.tencent.com/R6/R6_proj/trunk/R6Game // 查看当前目录所在分支从http://tc-svn.tencent.com/R6/R6_proj/trunk/R6Game合并过来的时间线 注:merge信息会保存在svn propget svn:mergeinfo属性中
解释说明:
① 分支branches/20200512_svn_47877_MirrorTrunk/R6Game是从主干trunk/R6Game的47877版本拉取得到的
② 最新的一次是从主干trunk/R6Game的52748版本merge过来的
③ 主干trunk/R6Game最近的提交为56064
svn copy TRUNK_URL TRUNK_BRANCH // 从主干TRUNK_URL拉取分支TRUNK_BRANCH
svn del main.c // 删除本地当前目录下的main.c文件
svn del TestDir // 删除本地当前目录下的TestDir文件夹
svn del TRUNK_URL\main.c –m "comments" // 删除TRUNK_URL服务器上的main.c文件
svn mv TRUNK_URL\main.c TRUNK_URL\main2.c –m "comments" --force-log // 将服务器上的TRUNK_URL\main.c改名为main2.c
svn mv main.c main2.c // 将当前目录下main.c重命名为main2.c
svn up // 更新当前目录(递归子目录)的svn到最新版本
svn up --ignore-externals // 更新当前目录(递归子目录,忽略external外链)的svn到最新版本
svn up main.c // 更新main.c文件的svn到最新版本
svn up d:\TestDir // 更新d:\TestDir目录(递归子目录)的svn到最新版本
svn up -r1665 TestDir // 更新当前目录下的TestDir目录(不含external递归子目录)的svn版本到1665
-----------------------------------------------------------------------------------------
svn up --set-depth empty // 将当前目录(递归子目录)清空
svn up --set-depth infinity // 完全信赖服务器来更新当前目录(递归子目录)
注:当更新时出现以下错误时,可使用上面两条命令刷新本地cache来解决:Error Checksum mismatch while updating
-----------------------------------------------------------------------------------------
svn resolve --accept working same_time.txt // 使用自己的版本来解决same_time.txt文件的冲突
svn resolve --accept theirs-conflict same_time.txt // 使用别人的版本来解决same_time.txt文件的冲突
svn resolve --accept theirs-full same_time.txt // 完全使用服务器的版本来解决same_time.txt文件的冲突
----------------------------------------------------
#我的
same_time.txt.mine
#冲突前的
same_time.txt.r10
#冲突的
same_time.txt.r11
<<<<<<<
mine content
============
A content
>>>>>>> .r11
----------------------------------------------------
(mc) mine-conflict
丢弃从服务器收到的, 与本地冲突的所有修改, 但是接受不会产生 冲突的修改
(tc) theirs-conflict
丢弃与服务器产生冲突的所有本地修改, 但是保留不会产生冲突 的本地修改
(mf) mine-full
丢弃从服务器收到的该文件的所有修改, 但是保留该文件的本地修改
(tf) theirs-full
丢弃该文件的所有本地修改, 只使用从服务器收到的修改
----------------------------------------------------
svn revert . // 丢弃当前目录下所有的修改
svn revert main.c // 丢弃当前目录下main.c文件的修改
svn revert -R . // 丢弃当前目录下(递归子目录)所有的修改
svn revert -R d:\TestDir // 丢弃d:\TestDir目录下(递归子目录)所有的修改
svn revert -R TestDir // 丢弃当前目录TestDir目录下(递归子目录)所有的修改
svn cleanup // 清理当前目录下本地未完成svn操作的状态信息
svn cleanup --remove-unversioned // 清理当前目录下本地未完成svn操作的状态信息,并删除所有非版本控制的文件和目录
svn cleanup TestDir // 清理当前目录TestDir目录下本地未完成svn操作的状态信息
svn log // 查看当前目录的历史修改
svn log main.c // 查看当前目录下main.c的历史修改
svn log -l 10 -v //查看当前目录下最新10条log,并打印出每次变更的文件列表
svn log -r {2017-03-24}:{2017-03-25} //查看当前目录下从 [ 2017-03-24, 2017-03-25 ) 之间的记录,要是时间反过来写就是先打印2017-03-25的
svn log -r "{2018-04-20 15:00:00}:{2018-04-20 17:00:00}" //查看当前目录下从 [ 2018-04-20 15:00:00, 2018-04-20 17:00:00 ) 之间的记录
svn log -r 1665 d:\TestDir //查看d:\TestDir目录下版本号为1665的log信息
svn log -r --xml 1665:2015 //以xml形式查看版本号为 [ 1665, 2015 ] 的log信息
svn propset svn:executable on KE.sh // 为当前目录下的KE.sh增加可执行属性(Unix/Linux/MacOSX等)
svn propset svn:needs-lock on d:\TestDir\* // 为d:\TestDir下所有文件增加加锁属性
svn propset svn:externals "WebUI http://xxx/trunk/Game/WebUI" . // 在当前目录下创建一个externals的外链:新建WebUI目录并将其指向http://xxx/trunk/Game/WebUI
svn propset svn:externals -F externals.txt . // 使用externals.txt文件中externals配置来在当前目录下创建多个外链
========== externals.txt ============
WebUI http://xxx/trunk/Game/WebUI
Content http://xxx/trunk/Game/Content
svn propset svn:ignore -R "*.pdb *.ncb *.suo" Src // 为当前目录下的Src目录及递归子目录增加.pdb .ncb .suo后缀名过滤属性(在当前目录下点击Add获得列表中将过滤掉.pdb .ncb .suo后缀名的文件;但可以通过直接选择目标文件Add)
svn propedit svn:ignore "*.pdb *.ncb" Src // 为当前目录下的Src目录过滤属性修改为.pdb .ncb后缀名(必须要先通过svn propset创建svn:ignore属性才行使用svn propedit进行编辑)
svn propset svn:ignore '*' spool // 忽略当前目录下的spool目录中的所有文件(Add列表文件列表中不显示)
svn propset svn:ignore 'images' // 忽略当前目录下的images文件夹(Add列表文件列表中不显示)
svn propset svn:global-ignores -F E:\Test\svn-ignore.txt . // 使用E:\Test\svn-ignore.txt文件中的配置来在当前目录下设置过滤内容
========== E:\Test\svn-ignore.txt ============
*.class
*.jar
*.war
*.ear
target/
.classpath
.settings/
.project
.metadata
bin/
++++++++++++++++++++++++++++++
svn:ignore与svn:global-ignores区别:
① svn:ignore:只对当前目录有效
svn:global-ignores:是全局有效,就是所有目前都有效
② svn:ignore:必须每个工作目录都要设置,个性化配置
svn:global-ignores:只需要配置一次,使用方便
svn propset svn:keywords "Author Date Revision" test3.txt // 为test3.txt设置Author Date Revision关键字
注:在test3.txt中的$Author$、$Date$、$Revision$将被替换成如下内容
$Author: chen $
$Date: 2018-07-19 16:36:46 +0800 (周四, 19 七月 2018) $
$Revision: 775107 $
++++++++++++++++++++++++++++++
$Date$ 提交的日期
$Revision$ 提交的版本号
$Author$ 提交的作者
$HeadURL$ 此文件在版本库中的 URL
$Id$ 上述四个关键字的压缩组合
svn propdel svn:executable KE.sh // 删除KE.sh上的可执行属性(Unix/Linux/MacOSX等)
svn proplist KE.sh // 查看KE.sh的属性
svn propget svn:externals -R // 查看当前目录下(递归子目录)所有具有svn:externals属性的目录
svn propget svn:mergeinfo // 获取当前目录的merge信息,如下
/trunk/RGame:47878-52747,52784,52793,52797,52832,52846,52893,52904,53048,53057,53177,53188-53190,53219 // 当前分支从主干/trunk/RGame合过来的所有commit id集合
svn st [-v] // 查看本地文件状态,可以看到当前目录下所有的改动
-v: 可以显示所有的文件信息,包括未修改的。
-u: 可以用”*”标识有更新的文件
文件状态:
? scratch.c (不在版本控制中)
A stuff/loot (新加文件,未提交)
A stuff/loot/new.c
D stuff/old.c (删除文件,未提交)
M bar.c (修改文件,未提交)
C cc.c (有冲突未解决的)
svn lock ATD8-Test_Main.udk // 锁定当前目录下的ATD8-Test_Main.udk文件
svn lock -m "adjust size" --force ATD8-Test_Main.udk // 强制锁定当前目录下的ATD8-Test_Main.udk文件(若被其他人锁定,则偷锁),并写上adjust size的日志
svn unlock ATD8-Test_Main.udk // 解锁当前目录下的ATD8-Test_Main.udk文件
svn diff DefaultADGame_2.ini // 查看DefaultADGame_2.ini文件的当前修改
===================================================================
--- DefaultADGame_2.ini (revision 773213)
+++ DefaultADGame_2.ini (working copy)
@@ -6631,7 +6631,7 @@
Level1StateCommandListHard=Rush
Level1StateCommandListHard=SwingBlade
Level1StateCommandListHard=Rush
-Level1StateCommandListHard=Garbage
+Level1StateCommandListHard=Idle
Level1StateCommandListHell=Idle
Level1StateCommandListHell=Laser
注:-Level1StateCommandListHard=Garbage // -表示删除
+Level1StateCommandListHard=Idle // +表示增加
svn diff -c 772500 DefaultADGame_2.ini // 查看DefaultADGame_2.ini文件772500版本与其上个版本的差异
svn diff -r 772500 DefaultADGame_2.ini // 查看DefaultADGame_2.ini文件772500版本与当前工作目录版本的差异
svn diff -r 772688:773161 DefaultADGame_2.ini // 查看DefaultADGame_2.ini的772688与773161版本差异
===================================================================
--- DefaultADGame_2.ini (revision 772688)
+++ DefaultADGame_2.ini (revision 773161)
@@ -6551,7 +6551,7 @@
RushCount=1
LaserIdleDuration=22.0f
FixedLaserStartFireSeconds=2.4f
-FixedLaserStopFireSeconds=1.2f
+FixedLaserStopFireSeconds=1.6f
MovableLasersStartFireSeconds=1.0f
GrenadeCount=5
+++++++++++++++++++++++++++++++++++
svn版本说明:
svn-win32-1.5.4
svn-win32-1.6.16
svn-win32-1.7.13
svn-win32-1.8.10
... ...
各个版本可以从这儿下载:https://sourceforge.net/projects/win32svn/files/
可以使用以下方法来判断本地svn目录是用的哪个版本拉取的:
① 若存在.svn\entries文件,则读取其中记录的版本号;不存在则读取.svn\format文件中记录的版本号V
注:1.7.4等高版本的svn 把.svn文件夹只放置到签出root目录,子目录不再有.svn
② 若V = 7,则svn的版本为1.3
若V = 8,则svn的版本为1.4
若V = 9,则svn的版本为1.5
若V = 10,则svn的版本为1.6
若V = 12,则再执行命令sqlite3.exe .svn\wc.db "PRAGMA user_version",返回值为R(注:sqlite3.exe可以从这儿下载)
(a) 若R = 29,则svn的版本为1.7
(b) 若R = 31,则svn的版本为1.8