ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SVN与Git共存指南:双版本控制工具的高效工作流与迁移实战

SVN与Git共存指南:双版本控制工具的高效工作流与迁移实战 进公司第一天leader丢给你一个SVN地址回工位坐下你习惯性地敲下git init然后开始纠结一个问题这两套版本控制工具到底能不能在一台电脑上和平共处答案是不仅能而且对很多人来说这是日常工作的标准操作。我见过大量团队公司主仓库是SVN程序员自己私下维护Git仓库做本地版本管理也见过团队从SVN迁移到Git但在过渡期必须双轨并行好几个月还有人要同时维护公司SVN项目和开源Git项目电脑上两种工具整天换来换去。这篇文章就把这种“同时使用SVN和Git”的完整玩法讲透包括安装配置、日常协作流程、git-svn桥接、仓库迁移以及一堆我踩过坑之后才总结出来的注意事项。1. 为什么需要同时使用SVN和Git几个真实工作场景先说个结论SVN和Git并不是“有你没我”的对手关系它们是两套独立的版本控制实现底层数据结构完全不同安装在同一台机器上根本不会冲突。真正需要想清楚的是你到底处于哪种工作场景以及两种工具各负责哪一段流程。1.1 三种最典型的“双仓库”需求第一种公司强制SVN个人习惯Git。这种在传统企业、银行、外包项目里太常见了。服务端的代码仓库由运维统一管理权限、审计都要走SVN你没有选择权。但你习惯用Git做本地提交、随时回滚、开分支实验那就完全可以在SVN工作副本里再初始化一个Git仓库让Git当本地的“后悔药”。第二种团队正处于SVN向Git迁移的过渡期。规划好了新仓库地址但业务还在跑不可能停下手头工作“搬迁”一天。常见做法是代码继续提交到SVN同时用git-svn把SVN仓库实时镜像到本地Git仓库等团队成员陆续切换过来最后彻底关掉SVN。这个过程可能持续几周到几个月双轨是唯一选择。第三种多个项目本身就用了不同的版本控制工具。开源项目用Git客户要求源码托管在公司的SVN服务器自己接的私活用Git公司项目用SVN。这种情况没有技术包袱就是两种工具都要熟练操作切换项目时别把命令记混就行。1.2 两个工具能共存的前提底层数据结构不冲突很多人担心“同一个目录里既有.svn又有.git会不会打架”答案是基本不会前提是你别乱改对方的元数据目录。SVN在工作副本里每个目录都会生成一个.svn文件夹Git则是在仓库根目录生成一个.git文件夹两者是独立存在的。但从数据模型上两者的设计哲学完全不同这也决定了它们适合的协作模式维度SVNGit架构集中式所有历史在服务器分布式每个克隆都是完整仓库版本号全局递增数字r1、r2…40位哈希值提交体验大多数操作需要联网本地提交毫秒级完成分支/标签目录拷贝成本高合并靠svn merge分支是轻量指针合并有完整三方合并算法历史记录单线为主改名/移动后日志易断裂有向无环图任何操作可追溯空目录可以纳入版本控制默认不跟踪空目录离线操作基本不能可以完整使用理解这层差异你就知道为什么太多人“用着SVN却不甘心”——不是SVN不好用而是它解决不了本地快速迭代、安全回滚、离线工作这些需求。而Git又恰恰在落地时碰到了企业服务器的管理习惯问题。两者共存本质上是各取所长SVN负责与团队同步Git负责个人代码管理。2. Windows环境下的安装与配置让SVN和Git和平共处如果要在一个干净的环境里把两套工具都装好并且让IDEA、VSCode、Visual Studio都能正确识别有几个安装细节必须提前注意否则后面会遇到一堆莫名其妙的问题。2.1 安装TortoiseSVN时最容易漏掉的一项TortoiseSVN俗称“小乌龟”是Windows上最主流的SVN客户端。下载地址是官网TortoiseSVN.net安装包本身不大一路Next即可。容易漏掉的一步安装进行到“Select Additional Tasks”页面时默认没有勾选command line client tools这项。如果你只把TortoiseSVN当右键菜单工具用不勾选也没关系但如果你要在IDEA里配置SVN、或者想用svn命令行就必须勾选。IDEA、Visual Studio等IDE集成的SVN本质上调用的是svn.exe而不是TortoiseSVN的右键菜单。安装完成后如果发现没装命令行工具无需卸载重装直接重新运行安装包选择“Modify”勾上该组件即可。装完以后svn.exe位于C:\Program Files\TortoiseSVN\bin\svn.exe这个路径在IDE配置时会用到。小乌龟的汉化包中文语言包建议同步安装安装后在Settings - Language里切换语言。特别注意语言包版本必须和主程序版本完全一致否则无法识别。2.2 Git安装PATH、换行符、中文路径一个都不能少Git for Windows的安装包从git-scm.com下载安装过程中的几个选项很多新手会直接点下一步但我建议按下图思路处理Select Components勾选Git Bash Here、Git GUI Here这两个右键菜单入口平时太好用了。Default branch name建议选main新仓库默认分支名是main现在各大Git平台都支持。Adjusting your PATH environment务必选Git from the command line and also from 3rd-party software这个选项会把git.exe自动加到系统PATH否则在CMD、PowerShell里敲git会提示“无法将git识别为cmdlet”之类的错误。Checkout Windows-style, commit Unix-style line endings这是默认选项一般保持默认即可。但对SVN和Git混用的目录我后面会专门讲行尾符的坑。装完后打开Git Bash验证一下运行git --version git config --global user.name 你的名字 git config --global user.email 你的邮箱用户信息不配置的话Git提交会报黄字警告而且历史里的作者信息会乱。这一点和SVN不同SVN通常直接使用系统登录名Git必须显式配置。顺手做两件事一是执行git config --global core.quotepath false解决中文文件名在Git log里显示成八进制转义序列的问题——如果你搜过“git -c core.quotepathfalse”应该明白我在说什么二是确认凭据管理器可用这个放到第5章讲免密时详细说。2.3 IDE里的SVN与Git协调配置现在主流IDE几乎都内置了Git支持SVN则要分情况处理。IntelliJ IDEA包含Android StudioSettings - Version Control - Subversion在Path to svn executable里手动指定C:\Program Files\TortoiseSVN\bin\svn.exe然后点Test确认。Git配置在Settings - Version Control - Git系统通常会自动检测到git.exe。IDEA支持一个项目里同时存在多个VCS你可以在Settings - Version Control里看到当前被识别的目录映射比如某个子目录是SVN另一个子目录是GitIDE会自动切换对应的菜单。Visual StudioVS的Git支持是原生集成的SVN则需要安装扩展比如VisualSVN。如果你用的是较新的VSGit的按钮就在解决方案管理器旁边SVN仓库则建议直接用TortoiseSVN右键操作或者装扩展后在解决方案上右键会出来SVN相关的Commit/Update菜单。VSCodeGit是内置的SVN要靠扩展。在扩展市场搜“SVN”安装下载量最高的那个一般叫SVN作者是JohnstonCode它会调用本地的svn.exe。打开SVN工作副本目录时左侧源代码管理面板会变成SVN操作面板可以查看改动、提交、更新。VSCode的多根工作区里不同子文件夹分别属于SVN和Git也能正常识别。IDE配置这块的核心经验是只要能在一台机器上同时找到git.exe和svn.exe并且两个命令行工具都能正常工作IDE层面就不会出大问题。3. 双轨并行的三种日常工作流直接照抄这一章是整篇文章的核心。工具装好了IDE也配好了那同一个项目里到底怎么同时用两套版本控制我给出三种方案覆盖从纯命令行到纯图形界面的全诉求。3.1 方案ASVN做主仓库Git做本地后悔药这是我最推荐的非迁移场景方案适合“公司仓库是SVN但你想要本地版本管理能力”的情况。原理在SVN的工作副本里执行git init启动一个不关联任何远端的纯本地Git仓库。SVN负责和团队同步Git负责你个人每天的文件快照管理。初始化步骤# 第一步迁出SVN工作副本 svn checkout http://svn.example.com/project/trunk project cd project # 第二步创建.gitignore把.svn目录排除掉 echo .svn/ .gitignore # 第三步初始化本地Git仓库 git init git add . git commit -m init local repo这里最关键的就是.gitignore必须排除.svn/否则Git会把每个目录下的.svn文件全部记录下来一次commit里全是乱七八糟的元数据。我见过有人忘了这一条Git仓库里攒了几千个.svn文件后来清理起来极其痛苦。日常提交节奏我强烈建议按这个固定顺序svn update——先拉取服务器上别人提交的代码改代码svn diff——检查自己的改动是否符合预期svn commit——把改动推送给团队git add .git commit -m ...——给本地Git留一个快照。为什么要把git commit放在最后因为Git快照记录的是“服务器上已经存在的最终状态”如果你先git commit再svn commit万一svn commit因为冲突失败你的本地Git快照就记录了一个“团队里别人都看不到的状态”之后想回滚就会和服务器状态对不上。这个方案能干什么改坏了代码在SVN提交前你可以用git diff看自己改了什么git checkout -- file丢弃文件改动想开分支做个大改动git checkout -b experiment开Git分支随便折腾SVN工作副本完全不受影响实验成功再git checkout mastergit merge experiment;每次svn update后Git status能直观告诉你工作区哪些文件发生了变化比svn status的信息密度高不少。注意这套方案里Git仓库不要添加任何remote不要执行push。因为Git本地仓库只是你监控版本、做快照的辅助工具。一旦你哪天加了remote并push到某个Git平台那另一套代码历史就和SVN完全分叉了最终只会把自己搞晕。3.2 方案B用git-svn把SVN仓库当成Git仓库来用如果你不想看到SVN的命令行、不想装TortoiseSVN只想纯粹用Git操作那就用Git自带的git-svn桥接工具。它是Git官方提供的SVN兼容层你日常用Git命令它自动翻译成SVN协议操作。首次克隆# 标准SVN布局trunk/branches/tags加 -s 参数 git svn clone -s http://svn.example.com/project my-local-repo # 如果仓库不是标准布局手动指定 # git svn clone -T trunk -b branches -t tags http://svn.example.com/project repo首次克隆会把SVN服务器上的全部历史拉到本地如果服务器历史很长会很慢。可以从指定版本开始加速git svn clone -s -r 1000:HEAD http://svn.example.com/project repo上面的命令只从r1000开始拉取之后用增量命令补齐。日常开发流程# 拉取SVN服务器上别人的提交 git svn rebase # 正常用git做本地提交 git add . git commit -m commit message # 把本地提交推送到SVN服务器 git svn dcommit注意这里不是git push是git svn dcommit。它会把你本地的一段Git提交逐个转换成SVN提交每个提交对应一个SVN版本号。执行后打开SVN Log会看到你那条Git commit的message和git-svn-id信息。这个方案的坑比方案A多重点讲一下git-svn只工作在它克隆的那个SVN分支上。你在本地可以开Git分支体验分支的便利但合并多个Git分支后直接dcommit到SVN官方不支持会因为merge的父子关系无法映射到SVN而报错。正确做法是在SVN仓库里正儿八经地创建分支clone到本地后切到对应的remote分支上操作千万不要在dcommit前用git rebase -i改写已提交的历史。SVN历史上已经出现了这些提交记录你再改本地哈希dcommit时会出现大量冲突和诡异错误。本地随便改但改完要赶在推送前确认git svn rebase和git pull --rebase不一样前者是“把SVN上新增的提交拉到本地并把你的提交rebase到它们之上”是整个桥接机制的自动处理流程。不要试图用standalone的git pull来替代会搞乱git-svn的remote状态。方案B适合什么场景适合你个人有能力绕开SVN客户端且团队里其他人都还在用SVN做主流协作。你是“少数派”但通过git-svn你能保留完整的Git体验。3.3 方案C图形界面党怎么用TortoiseSVN TortoiseGit装一个TortoiseGitGit的小乌龟它会和TortoiseSVN住进同一个右键菜单里。两个小乌龟的版本控制操作如下SVN小乌龟管SVN Update、SVN Commit、SVN CheckoutGit小乌龟管Git Sync、Git Pull、Git Push、Git Commit。右键菜单里两类操作会同时出现这时候最容易犯的错就是“心态混乱”。我的建议是同一个目录里认准一条主线。比如你处于方案ASVN主仓库Git本地快照那就在菜单上养成习惯提交给团队一定是点SVN Commit记录本地版本一定用Git Commit。两个小乌龟的图标外观很相似新手真的会点错。另外提醒一句TortoiseGit默认的忽略规则和TortoiseSVN的“全局忽略”是各自独立的。SVN仓库里维护的svn:ignore属性、svn:global-ignores属性不会自动同步到Git的.gitignore。如果你同时用两套工具就要在两个地方都维护忽略规则漏一个都会导致该忽略的文件被误提交。4. 从SVN到Git的迁移实操历史、作者和分支一个都不能丢工作流说完了再讲一个更进阶的用法整个团队决定从SVN迁到Git怎么把历史仓库完整“挪”过去。这一步很多人喜欢手动把代码复制过去只保留最新代码但丢失历史会让日后排查问题变得非常困难。正确做法是用git-svn做一次完整迁移。4.1 迁移前要准备的三样东西第一SVN仓库的目录结构。先确认是标准布局还是非标准布局。标准布局指根目录下有trunk、branches、tags三个目录迁移最方便非标准布局需要额外指定参数否则无法正确识别主干和分支。第二作者映射文件。SVN记录里存的是用户名Git提交需要“用户名 邮箱”。要生成一个映射文件把每个SVN用户的用户名映射成Git身份。Git Bash里执行svn log -q | awk -F | /^r/ {sub(^ , , $2); sub( $, , $2); print $2 $2 $2example.com} | sort -u authors.txt执行完打开authors.txt手动检查一遍把占位邮箱改成真实邮箱例如zhangsan Zhang San zhangsanexample.com lisi Li Si lisiexample.com第三目标Git仓库。在你的Gitee、GitHub或GitLab上建一个空仓库拿到仓库地址。建议不要直接push到团队正在使用的Git仓库先在本地迁移验证无误后再推送。4.2 用git svn clone完成仓库转换假设SVN地址是http://svn.example.com/project执行git svn clone -s --authors-fileauthors.txt -r 1000:HEAD http://svn.example.com/project project-git参数说明-s自动识别标准布局trunk/branches/tags--authors-fileauthors.txt指定作者映射文件这样每个Git提交的author信息才是规范的-r 1000:HEAD只迁移从r1000开始到最新版本的历史。首次迁移建议限制范围先跑通流程再补全否则SVN仓库若有两三千个版本clone时间会非常久。如果SVN仓库历史很长你可能需要分步增量拉取。第一次clone完成后用如下命令继续拉取之后的新提交git svn fetch git svn rebasegit svn fetch负责抓取SVN上新提交的对象git svn rebase负责将这些提交整合进当前分支。4.3 分支、标签与远端推送的收尾工作迁移完之后本地看起来是一个完整的Git仓库但你执行git branch -a看一下会发现SVN上的分支以remotes/origin/xxx的形式存在标签也都在refs/remotes/origin/tags/xxx下。需要将它们转换成本地分支和真正的Git标签然后推送到新Git平台。把SVN分支转成Git分支进入project-git目录for ref in $(git for-each-ref --format%(refname:strip2) refs/remotes/origin | grep -v ^tags/); do git branch $ref refs/remotes/origin/$ref done把SVN标签转成Git标签for ref in $(git for-each-ref --format%(refname:strip3) refs/remotes/origin/tags); do git tag $ref refs/remotes/origin/tags/$ref done然后推送全部内容git remote add origin gitgitee.com:yourname/project.git git push -u origin --all git push -u origin --tags推送完成后用浏览器打开新仓库的“标签”页和“分支”页确认数量是否符合预期。一旦确认无误SVN老仓库不必急着删除可以让团队成员先读新仓库过一两个月再关停。迁移过程中有个很常见的坑SVN的空目录不迁移过来。Git默认不跟踪空目录而SVN是可以跟踪空目录的。如果某个模块目录在SVN下是有意保留的空目录迁移后需要手动加个.gitkeep文件再提交。怎么发现在SVN仓库里执行svn list对比每个目录在Git里是否存在数量不多就手动处理目录很多就用脚本生成占位文件。5. 常见问题与排查技巧实录最后把我在实际工作中遇到频率最高的问题和解决方案整理出来直接照着排查就行。5.1 命令行工具找不到先查这三处问题一“无法将‘git’项识别为 cmdlet、函数、脚本文件或可运行程序的名称。”这是Windows下Git没加到PATH的典型报错常见于IDEA内置终端或PowerShell窗口。解决重新运行Git安装包选择Modify在“Adjusting your PATH environment”步骤确保选中了“Git from the command line”装完重开终端。问题二“svn: command not found”在纯命令行环境里敲svn报错说明TortoiseSVN命令行组件没装。重新运行TortoiseSVN安装包Modify勾上command line client tools。问题三IDEA里SVN操作报E170013、E230001。先确认Settings - Version Control - Subversion里的svn.exe路径正确并点击Test。如果路径正确还报错通常是服务器地址无权限或证书问题用TortoiseSVN先正常访问一次保存认证信息后再回到IDEA。5.2 SVN和Git免密配置的两种思路SVN免密首次连接SVN时认证弹窗里勾选“Save authentication”Windows凭据管理器会记录下来之后更新、提交不再弹密码。如果没弹窗可以用svn auth命令查看当前保存的认证记录。清理凭据则进入控制面板 - 凭据管理器 - Windows凭据找到对应条目删除。Git免密分HTTPS和SSH两种方式HTTPS方式Git for Windows自带的Git Credential Manager会帮你保存账号密码。强制开启git config --global credential.helper managerSSH方式生成密钥ssh-keygen -t ed25519 -C your_email公钥.pub文件内容添加到Gitee/GitHub的SSH公钥列表私钥留在本地。克隆地址选SSH推送时就不用输入密码。5.3 混合使用中最容易踩的四个坑坑一.svn被误纳入Git仓库。一旦.svn/被git add进去每次SVN更新导致.svn目录内容变化Git status就是一坨红色。已经误提交的执行git rm -r --cached .svn git commit -m remove .svn from git然后在.gitignore里补上.svn/。坑二行尾符问题导致所有文件都显示为modified。Windows下SVN默认把文件以CRLF保存在工作副本Git配置了core.autocrlftrue时也会做CRLF/LF转换。两套机制叠加极容易出现“我明明没改文件git status却显示一堆改动”的情况。处理在混用目录下执行git config core.autocrlf false然后git checkout .重新刷新工作区。或者更简单根目录的.gitattributes里统一声明文本类型。坑三文件名大小写不一致。Windows文件系统默认不区分大小写但SVN和Git都认大小写。假如你新增foo.js、删除Foo.js在SVN上提交成功了Git里会出现两个文件并存反过来在Git上操作也可能让SVN状态混乱。解决涉及改文件名时成对操作先删旧文件再add新文件避免同一个文件在仓库里出现两个“大小写不同”的记录。坑四git-svn克隆时报“Unable to determine upstream SVN information”。这是SVN仓库不是标准布局导致的。用-T -t -b显式指定三个目录或重新确认仓库结构。5.4 问题速查表现象可能原因解决办法git命令找不到PATH未配置重装并勾选Git from the command linesvn命令找不到TortoiseSVN未装命令行组件重装勾选command line client toolsIDEA无法连接SVNsvn.exe路径错误在IDEA的Subversion设置里手动指定并Testgit status大量显示修改core.autocrlf与SVN换行冲突设置core.autocrlf false后checkout.svn目录出现在git里缺少.gitignore规则git rm -r --cached .svn补充忽略git svn dcommit报Merge冲突本地多个分支合并后推送SVN避免在git-svn里做Git merge回退后重新提交迁移后标签消失SVN标签未转换用for-each-ref循环生成本地git tag中文文件名显示转义core.quotepath默认开启设置core.quotepath false每次git push都要密码未配置凭据或SSH密钥credential.helper或ssh-keygen配置公钥最后说点实在的如果你也打算在同一台电脑上把SVN和Git都跑起来我个人的建议是不要一开始就想着用git-svn这种骚操作先老老实实用“SVN做远端 Git做本地快照”的双轨模式跑两周。这种模式最稳出错也就是本地Git仓库乱了不影响团队其他人等SVN和Git两套思维在你脑子里切换自如了再去碰git svn rebase和dcommit胜率高得多。还有一个我踩过几次坑后养成的习惯不管用哪种双轨方案每天下班前检查一次“远端状态”。SVN就是svn status、svn log看有没有未提交Git就是git status看有没有未push的分支。两套工具同时用最怕的不是技术报错是你自己忘了哪个改动提交到哪边了。定点检查习惯养成这比任何配置技巧都管用。
返回列表