ARTICLE DETAIL

资讯详情

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

SVN与Git共存实战:一台电脑上高效管理双版本控制

SVN与Git共存实战:一台电脑上高效管理双版本控制 说实话现在还有多少人同时在用SVN和Git两个客户端干活我之前在软件团队里就长期处于这种状态老项目全部挂在SVN上新项目又要求用Git做代码协作于是一台电脑上既装着小乌龟TortoiseSVN又装着Git Bash。一天下来两个工具来回切换是常事最麻烦的不是操作本身而是搞不清楚“哪个文件到底该往哪个库里提交”“两套工具的忽略规则会不会互相干扰”“IDEA里SVN插件和Git插件能不能完美共存”。这些问题我全踩过一遍花了不少时间才理顺。这篇文章就把这套“双版本控制”的完整实践经验写下来。如果你正在经历SVN向Git迁移的过渡期或者个人同时维护公司SVN仓库和个人Git仓库又或者刚好需要在一台机器上给项目配齐两套版本控制工具那这篇内容应该能帮上忙。我会从工具安装、工作流设计、日常操作一直讲到常见报错排查尽量让不同基础的朋友都能直接照着做。1. 为什么我会同时用上SVN和Git1.1 从集中式到分布式的版本控制演进很多新接触版本控制的同学可能不太理解为什么SVN和Git在现代开发里还在同时出场。简单说这两个工具的底层思路差别非常大。SVN是集中式版本控制系统的代表。它的工作模式是代码必须提交到中央服务器版本历史也集中在服务器上咱们本地的代码只是一个“工作副本”提交、更新、查看日志都得连上中央仓库。它的优点在于权限模型简单粗暴目录级别就能控制谁能读、谁能写非常适合企业级的管理方式。缺点是分支和合并的成本比较高一旦断网很多操作就做不了。Git是分布式版本控制系统的代表。每位开发者本地都有一份完整的仓库历史绝大多数操作在本地就能完成不依赖服务器分支的创建和切换非常轻量合并也比SVN强大得多。这也是现在开源社区、互联网公司普遍采用Git的核心原因。用生活化一点的方式去理解SVN像一个公司档案室所有人要去借阅文件修改改完再放回去档案室记录每一次借阅和修改记录Git则像每个人都有整套档案的副本你可以随时在自己的小桌板上改改完再把成果合并回去不需要每次修改之前都先去档案室借一次。1.2 现实项目里两类工具并存的典型场景我接触过好几类同时使用SVN和Git的真实场景不是在想象中而是实际发生的第一类是公司迁移期的并存。旧系统已经跑了五六年几十G的代码数据沉淀在SVN仓库里权限配置也早就稳定了新项目却已经全面切换到Git。迁移不是一天能完成的于是旧项目继续由SVN维护新项目由Git管理中间有一个持续几个月甚至一两年的并行窗口。第二类是同一个产品线的分支分化。有一种做法是主干放在SVN新的重构分支放在Git里做实验等Git分支稳定后再把代码回到SVN主线。这种“主库”和“实验库”分离的策略能降低迁移风险但也逼着开发同学同时掌握两套工具。第三类是外部协作约束。我一个朋友在外包公司甲方明确要求交付代码走SVN因为他们内部审计流程只认SVN的提交记录但公司内部的代码库、CI/CD链路早就全部跑通在Git上。于是同一个开发者白天在SVN上交付晚上在Git上开发内部工具两套仓库完全独立。第四类最普遍就是个人开发者自己。自己在公司维护SVN仓库里的老项目同时个人项目托管在Gitee或GitHub上用Git管理。出门在外两边都需要访问电脑上不可能只装一套客户端。这些场景都指向同一个核心需求在一台机器上把SVN和Git同时配好、配对并且不互相干扰。这个需求说起来容易实际操作中还是有不少门道的。2. 环境准备一台电脑同时装好SVN和Git2.1 Git的安装与初始配置Windows/Linux先说Windows。Git官方安装包在 git-scm.com 下载安装过程有几个地方值得注意。在“Select Components”这一步建议勾选“Git Bash Here”和“Git GUI Here”这样右键菜单直接出Git命令行入口用起来很顺手。在“Choosing the default editor”这一步如果你不熟悉Vim建议选Notepad或者VS Code而不是默认的Vim。否则后面写提交信息时不小心进入Vim编辑界面可能连退出都不会这是很多新手第一次用Git就卡住的地方。在“Adjusting your PATH environment”这一步务必选“Git from the command line and also from 3rd-party software”。这个选项会把Git加入系统PATH这样IDEA、VS Code以及其他工具都能直接调用git.exe也能在CMD和PowerShell里直接用git命令。很多同学遇到“无法将‘git’项识别为cmdlet、函数、脚本文件或可运行程序的名称”的报错根源基本都是这一步没选对。换行符转换方式我建议选“Checkout as-is, commit as-is”也就是默认不做自动转换。因为Git和SVN混用时如果Git把CRLF自动转成LF而SVN的svn:eol-style规则又要求CRLF两边就会来回报“文件已修改”非常折腾。统一保存原样最省心后面可以在.gitattributes里再精确控制不同文件的换行规则。安装完成后打开Git Bash验证版本并配置身份git --version git config --global user.name Your Name git config --global user.email your_emailexample.comuser.name和user.email会写进每次提交里一定要配好。如果公司或团队要求特定的用户名和邮箱也要按团队规范来配不要随手写个昵称。Linux桌面的安装要简单很多sudo apt install git # 或者 CentOS/RHEL 系列 sudo yum install git安装完同样执行git --version验证再配置user.name和user.email。2.2 TortoiseSVN小乌龟的安装与汉化Windows下最常用的SVN客户端还是TortoiseSVN大家习惯叫“小乌龟”。下载一定要去官方网站 tortoisesvn.net不要从第三方下载站随意下既麻烦又有安全风险。安装时有个非常容易被忽略的选项“command line client tools”。默认是不安装的但IDEA、VS Code以及一些脚本都会直接调用svn.exe如果你不装这些命令行工具后面常常会遇到IDE提示“Cannot find SVN command line client”之类的问题。推荐在安装时选择“Will be installed on local hard drive”把命令行工具一并装上。安装完成后TortoiseSVN在资源管理器右键菜单里会有体现但默认的菜单是英文的。中文语言包也去官网下载与你的TortoiseSVN版本、系统位数完全匹配的安装包安装完成后在Settings - Language里选择中文Simplified Chinese点击确定界面就切成中文了。Linux下SVN客户端通常直接用命令行模式sudo apt install subversion安装完之后svn --version试试能否正常输出版本信息。2.3 IDEA中同时接入SVN和Git如果你用的是IntelliJ IDEA或者同系列IDE同时接入两套版本控制是可以的但需要明确一点IDEA并不是靠“插件打架”来处理多VCS的而是靠“目录映射”来区分。对于不同的目录分别设置对应的VCS类型即可。打开SettingsWindows下是File - SettingsmacOS下是IntelliJ IDEA - Preferences进入Version Control菜单。你会看到“Directory Mappings”列表这里可以针对每个工作目录设置其使用的版本控制系统。比如把D:\legacy-project映射为Subversion把E:\new-project映射为Git。IDEA会根据目录里实际存在的.svn或.git元数据目录来自动识别所以只要目录边界清晰一般不会混乱。如果某个项目打开后没有自动识别出版本控制可以手动在VCS菜单里选择“Enable Version Control Integration”然后在下拉列表里选择Git或Subversion。如果IDEA提示找不到SVN命令行客户端去Settings - Version Control - Subversion里把“Use command line client”勾上并填上svn.exe的完整路径。默认一般位于“C:\Program Files\TortoiseSVN\bin\svn.exe”。Git这边Settings - Version Control - Git里可以检查并设置Git执行文件路径。IDEA通常会自动检测到git.exe如果没检测到手动指向“C:\Program Files\Git\cmd\git.exe”。3. 工作流设计SVN和Git怎么分工不打架3.1 明确仓库边界谁用SVN管谁用Git管工具装好只是第一步真正让双VCS并存在日常开发里不混乱的是边界清晰的工作流设计。我最想提醒大家的一点是同一个工作目录里千万不要同时创建.svn和.git这两个元数据目录。为什么呢因为SVN和Git管理文件状态的方式完全不一样。SVN在每个工作副本目录下会有.svn旧版本在每个目录都有1.7以后集中到根目录一个里面保存的是本地状态、基准副本、更新信息Git则在仓库根目录下有一个.git目录保存的是整个历史对象库、索引、配置信息。两套系统对同一批文件的状态判断逻辑是独立的彼此完全不知道对方。如果同一份文件同时被两边跟踪你会在SVN里看到“已修改”在Git里也看到“已修改”提交后两边互相覆盖轻则日志混乱重则把不相关的文件提交到错误的仓库里。所以我的第一条边界建议是目录级隔离。SVN管的项目工作目录里只有SVN元数据Git管的项目工作目录里只有Git元数据。哪怕两个项目内容高度相似、甚至就是同一份代码的两个用途比如一个维护版本、一个重构版本也不要放在同一个目录里去“省空间”。3.2 同一个工作目录同时对接两套版本库的方案有些朋友可能会问那我想用一个目录同时同步到SVN和Git仓库难道完全不行吗我的回答是能做但代价很大而且只适合特定场景不适合作为日常开发的主力方案。有种做法是用Git作为本地主版本控制再用SVN做发布网关。原理很简单本地开发完全在Git里做提交历史、分支合并都走Git需要对外发布时通过git svn工具把Git提交同步到SVN服务器。这个方案的核心命令是git svn clone http://svn.example.com/svn/project/trunk my_project cd my_project # 在 Git 里正常开发提交 git svn rebase git svn dcommitgit svn clone会把SVN仓库的提交历史转换成Git提交历史之后本地用Git工作流想从SVN拉最新变更时执行git svn rebase想把自己的提交推到SVN时执行git svn dcommit。但这里有几个非常现实的坑第一git svn会把本地提交一次性推送到SVN如果你的本地提交和SVN历史存在差异可能会有冲突问题第二它不支持SVN的svn:externals这类外部引用遇到就麻烦了第三团队其他成员如果还在用SVN他们会经常看到你不是一个修订号一个提交而是成批提交审计上不太好解释。因此git svn更适合作为个人迁移的桥梁不适合作为长期双写方案。还有一种相对省事的做法是“文件复制同步”把SVN和Git放到两个不同目录用脚本同步源代码文件但排除.svn和.git目录。这样虽然避免了元数据冲突但同步本身很容易出遗漏两个仓库的提交历史也没法对接只能作为临时过渡。如果是长期并行我强烈建议干脆接受“目录隔离”的方案。旧项目在SVN里维护新项目在Git里维护代码不交叉、历史不交叉、权限不交叉。真需要把一段代码从SVN搬到Git用导出的方式svn export出源码在Git仓库里import即可而不是直接拖动工作目录。3.3 图形客户端与命令行怎么选工具选择上我个人的倾向是Windows下SVN日常操作用TortoiseSVN右键提交、更新效率很高Git操作用命令行特别是分支合并、冲突解决、历史修改这类操作命令行比图形界面可控得多、也容易排查问题。如果确实不习惯Git命令行可以试试TortoiseGit也就是Git版小乌龟。它的操作习惯跟TortoiseSVN很接近右键菜单、提交界面、日志查看都类似从SVN切换过来的朋友上手会快一些。但要注意Git的分支模型和SVN差别很大TortoiseGit再怎么“傻瓜化”也替代不了你对Git底层概念的理解。IDEA里的内置Git和SVN集成也很好用。提交面板会按文件变更列出Diff查看历史、解决冲突都直观。我通常在IDEA里做代码diff和提交遇到复杂合并再跳到Git Bash或用TortoiseSVN的合并向导。还有一点经验命令行工具一定要装好不光是为了自己操作也是为了IDEA、VS Code这些IDE能调用。像VS Code里安装SVN插件后如果找不到svn.exe就等于白装。4. SVN侧实操拉取、提交、权限和分支处理4.1 把SVN项目拉取到本地SVN最常用的操作就是Checkout把服务器上的仓库分支拉到本地成为工作副本。在Windows资源管理器里右键要放置项目的目录选择“SVN Checkout...”在URL of repository里填入仓库地址比如http://svn.example.com/svn/project/trunkCheckout directory会自动指向当前目录版本一般保持HEAD Revision即可点击OK客户端会弹出账号密码提示输入后就开始拉取。命令行方式也很快svn checkout http://svn.example.com/svn/project/trunk D:\workspace\projectCheckout完成之后如果服务器上有提交历史本地不会保存那么多历史对象只有当前版本的文件以及.svn目录里的基准副本。这也是SVN和Git一个很大的区别Git clone会拉下完整历史SVN checkout只拉“当前快照 本地状态信息”所以大型仓库第一次checkout通常比clone的本地体积小但后续在线操作会受网络影响。还有一个需要留意的点如果团队SVN服务器只有trunk一个目录那就直接checkout trunk如果仓库结构是标准的trunk/branches/tags日常开发应该checkout trunk分支代码再checkout到其他目录不要在同一个工作副本里频繁切换。日常操作里右键菜单最常用的就是SVN Update更新、SVN Commit提交。提交时一定要把涉及文件选中写清楚提交信息不要用“修改了部分文件”这种敷衍信息。SVN的提交记录是不可随意篡改的一条好的提交说明能省很多历史排查时间。4.2 SVN用户权限与凭证配置SVN的权限控制主要在服务端不在客户端。服务端常见的权限配置有两种一种是SVN自带的svnserve passwd authz适合内网小团队另一种是配合Apache或者VisualSVN Server用HTTP/HTTPS协议可以跟Windows域账户、AD集成权限控制更细。对客户端来说只需要理解一件事仓库URL的协议决定了你的认证方式。svn://开头走svnserve通常在passwd文件里维护账号密码登录时输入的是仓库自己的用户名和密码。http/https开头走Apache或VisualSVN Server认证可能跟域账号或htpasswd绑定有时甚至支持单点登录。所以如果你从svn://切换到了http://却发现同一个账号登录不上不一定是你密码错了可能是两套认证体系根本不一样需要找管理员确认。客户端侧的常见报错有“svn: Authorization failed”或者“svn: E170001”说明登录认证通过不了要么账号密码错误要么当前用户对这个目录没有访问权限。先看URL对不对再确认服务端authz权限最后检查密码。“svn: E170013: Unable to connect to a repository at URL”多半是网络不通、仓库地址写错或者代理拦截。先ping一下服务器地址再确认端口是否开放比如http默认80svn默认3690还是在TortoiseSVN的Settings - Network里看代理配置。TortoiseSVN会把认证信息缓存到本地如果换了账号或改了密码需要清除缓存右键 - TortoiseSVN - Settings - Saved Data在Authentication数据区点击Clear。IDEA里如果遇到SVN账号信息变更也可以在IDEA的设置里清除密码或者重启后重新输入。4.3 SVN分支合并与版本回滚SVN的分支机制和Git差异很大。SVN里分支本质上是服务器目录的拷贝比如把trunk复制到branches/release-1.0。因为是基于目录的所以创建分支可以用svn copysvn copy http://svn.example.com/svn/project/trunk http://svn.example.com/svn/project/branches/release-1.0 -m 创建1.0发布分支很多人听说SVN分支很重其实对于svn copy这种服务器端拷贝来说并不会真正把整个源代码复制一遍而是以引用的形式创建新的目录树速度很快。真正重的不是创建而是后续合并因为SVN不记录分支血缘合并的时候你需要明确告诉它“把哪个URL的哪个版本范围合并过来”。合并的基本形式是# 先更新工作副本到最新 svn update # 把 trunk 上从 r100 到 r120 的改动合并到当前分支 svn merge -r 100:120 http://svn.example.com/svn/project/trunk合并过程中如果出现冲突SVN会把冲突文件标记出来文件里出现和标记。SVN不会像Git那样要求先commit再继续但你必须先手动处理冲突然后用svn resolve告诉客户端这个冲突已经解决svn resolve --accept working file.txt回滚在SVN里不是svn revert因为svn revert只是丢弃本地修改不改变仓库历史。要回滚仓库里已提交的版本正确的做法是反向合并# 把 r150 这次提交的改动反向应用回去 svn merge -c -150 http://svn.example.com/svn/project/trunk svn commit -m 回滚 r150 的改动从SVN的视角看回滚不是删除历史而是生成一次新的提交来抵消旧提交的影响。这一点和Git的revert非常相似只是语法不同。理解了这一点就不会再用svn delete直接删文件来“回滚”了。以下是我整理的一个SVN常用命令速查适合放在手边操作命令拉取仓库svn checkout 本地目录更新工作副本svn update查看状态svn status查看日志svn log添加新文件svn add删除文件svn delete提交修改svn commit -m 提交说明丢弃本地修改svn revert反向合并回滚svn merge -c -版本号解决冲突svn resolve --accept working5. Git侧实操克隆、提交和免密配置5.1 Git Bash基础命令流程Git Bash是我平时用得最多的终端。第一次拿到一个远程Git仓库时最常见的操作就是克隆git clone gitgithub.com:user/repo.git # 或者 HTTPS 方式 git clone https://github.com/user/repo.git克隆完成后仓库的完整历史就在本地了。日常开发流程可以简化为三件事先看状态和差异git status git diff再添加文件并提交git add . git commit -m feat: 增加用户登录接口最后推送到远程git push origin main这里想提醒一个很多人容易忽略的点git add .会把当前目录所有未忽略的变更全部加进来如果之前忘记写.gitignore很容易把临时文件、编译产物、甚至.svn目录一起提交进去。所以每次提交前先git status看清楚Staged文件列表。分支操作是Git比SVN舒服最多的地方git branch dev git checkout dev # 或者一条命令创建并切换 git checkout -b feature/login # 切回主干 git checkout main # 拉取最新代码推荐用 rebase 保持历史线性 git pull --rebase # 合并某个分支到当前分支 git merge feature/login为什么我推荐pull的时候用rebase因为多人共用同一个分支时如果直接pull默认的merge会产生很多“Merge branch xxx into xxx”的无意义合并提交历史很快就乱成一团。用rebase相当于先把本地提交放到一边拉取远程新提交再把自己的提交“重放”到最新提交之上历史会保持一根线看起来清爽很多。当然rebase也有一点要注意不要把已经推送过的提交随便rebase重写否则会影响其他人。5.2 HTTPS免密与SSH密钥配置Git访问远程仓库有两种主流协议HTTPS和SSH。两种都用得很多但免密配置方式完全不一样。HTTPS方式最简单Windows下安装Git时如果选了“Git Credential Manager”第一次推送时输入账号密码后凭据会被安全地保存在Windows凭据管理器里以后就不用再输入。如果想强制使用明文存储也可以设置git config --global credential.helper store第一条命令设置后第一次输入密码会保存到用户主目录下的.git-credentials文件里后续免密。但我个人不太推荐store模式因为它是明文存储万一机器被不相关的人拿到账号密码就暴露了。Windows上优先用manager-coremacOS上可以用osxkeychain都比明文稳妥。SSH方式需要先生成密钥对ssh-keygen -t rsa -b 4096 -C your_emailexample.com生成时会要求确认密钥保存路径和密码一路回车即可。完成后会在~/.ssh目录下看到id_rsa私钥和id_rsa.pub公钥一定要记住私钥永远留在自己机器上不能给任何人也不能上传到任何网站。5.3 Gitee/GitHub密钥配置与测试以Gitee为例登录网页版后进入“个人设置”-“SSH公钥”把id_rsa.pub里的完整内容复制粘贴进去添加即可。GitHub的位置是Settings - SSH and GPG keys - New SSH key操作类似。添加完之后测试连通ssh -T gitgitee.com如果回显“Hi xxx! You’ve successfully authenticated”说明密钥配置成功。GitHub同理ssh -T gitgithub.com如果你同时使用多个代码托管平台或者同一平台的不同账号可以借助~/.ssh/config文件来指定不同域名使用不同密钥。比如Host gitee HostName gitee.com User git IdentityFile ~/.ssh/id_rsa_gitee Host github HostName github.com User git IdentityFile ~/.ssh/id_rsa_github配置完后克隆地址可以简写成gitgitee:org/repo.git系统会自动使用id_rsa_gitee这个私钥进行认证。很多同学遇到过一个问题公司GitLab账号是A个人Gitee账号是B两边都配了SSH Key但连接时老是认证失败。大多数情况下就是因为没分Host别名默认用的都是id_rsa网络上的“多账号SSH配置”教程很多核心就是上面这招。5.4 Git项目里补充SVN时最该注意的忽略规则如果你同时负责一个原本是SVN管理的项目后来部分子目录迁到了Git最容易出事的就是忽略规则不一致。SVN的忽略规则设置在目录属性上命令是svn propset svn:ignore。Git的忽略规则写在.gitignore文件里。两边机制不同互相不识别。最常见的坑是在SVN项目里养成了Release目录直接提交的习惯迁到Git后忘了加.gitignore把几百MB构建产物推到Git仓库后续每次clone都痛苦不堪。在Git管理的目录里如果前面有人误操作执行了git init.git目录会把整个项目变成一个全新的Git仓库这时候如果不对.gitignore做清理最容易被误提交的就是.svn目录。针对“既有SVN元数据、又要纳入Git”的边界情况Git仓库里的.gitignore建议至少包含.svn/ *.class target/ build/ out/ dist/ *.iml .idea/SVN侧也可以在项目的根目录设置svn:ignore排除Git元数据目录和常见IDE配置svn propset svn:ignore *.class .git .idea target iml .两套忽略规则不是互相替代而是需要各自维护。否则SVN侧会试图提交.idea目录Git侧会愚蠢地把.svn目录也纳入版本管理等到两个仓库的“看似相同”的项目出现越来越多不一致文件时再想起来清理就晚了。6. 同时使用SVN和Git的典型问题与排查6.1 git命令无法识别的环境变量问题这是新手最常见也最容易解决的报错报错内容和网上搜索到的高频词完全一致git : 无法将“git”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。出现这个报错的原因只有一个你的终端PowerShell或CMD找不到git.exe所在路径。要么是安装Git时没选PATH相关选项要么是安装后没有重启终端。排查思路分三步第一步确认git.exe到底在哪。默认安装位置是C:\Program Files\Git\cmd\git.exe如果这个文件存在说明Git安装成功。第二步查看系统PATH环境变量里有没有包含上面的目录。Windows可以在“高级系统设置”-“环境变量”里确认。第三步如果PATH里没有分成两种情况处理嫌麻烦的话把C:\Program Files\Git\cmd手动加到PATH然后重启PowerShell或CMD更干脆的话重新运行Git安装包在Adjusting your PATH环境变量那一步选择“Git from the command line and also from 3rd-party software”安装完重启终端即可。有些同学是在IDEA或VS Code里遇到“Cant use Git: git.exe not found”之类的报错那就不是终端问题而是IDE没有找到Git执行文件。去Settings - Version Control - Git里手动指定git.exe路径再点击Test确认能读到版本号就正常了。6.2 SVN认证与权限相关报错SVN侧我遇到过很多次“authorization failed”这里有一个很微妙的点有时候你输入的账号密码在SVN服务器上是存在的但你对目标目录没有读权限或写权限客户端照样会报“认证失败”。所以遇到这个报错别急着怀疑密码先确认你是不是真的有权访问这个URL。另外“svn: E170013”这种网络类错误也经常出现在公司内网环境里。排查顺序是先确认服务器地址是否还能访问ping一下主机名看网络通不通。再看端口如果是svn://默认端口3690如果是http://默认80如果服务端改了端口URL里要写清楚比如http://svn.example.com:8080/svn/project。最后看代理。公司网络环境里如果本机配置了系统代理TortoiseSVN的HTTP请求可能走了代理代理又不允许访问内网SVN地址就会连接失败。解决办法是在TortoiseSVN的Settings - Network里设置不使用代理或把SVN服务器地址加入代理例外列表。还要提醒一点如果本地缓存了旧的认证信息服务器端密码又被管理员重置了即使输入新密码也可能持续登录失败。这时候在TortoiseSVN的Settings - Saved Data里清除认证数据再重新checkout或update强制弹出登录窗口重新输入。6.3 .git与.svn目录混用带来的坑这是我认为最值得单独列出来的一个问题因为它在“同时使用SVN和Git”的场景里几乎必然会发生一次。想象这种情况项目原本在SVN工作副本里有一天某个同事在项目根目录执行了git init想试试Git执行完发现好像不对劲又把.git目录删了或者没删直接开始用Git提交。第二次提交时Git status显示的变更文件里出现了.SVN目录如果没注意直接add .提交那.svn目录里面可能是几G的本地状态文件就全部被提交进了Git历史。从此这个Git仓库体积爆炸而且SVN的本地状态还会隔三差五变化Git里永远有一堆“已修改文件”。反方向的坑也存在如果项目先用Git管理后来又有人用TortoiseSVN check out到同一个目录那么SVN会在目录里创建.svn同样会让Git的提交面板一直提示多出未版本化文件。遇到这种混用情况最稳妥的处理方案不是“清理元数据”而是物理隔离。具体做法是用svn export命令导出一份干净的源码到临时目录这个导出的目录不带.svn只包含源文件。用git clone或git init在另一个新目录里建立干净的Git仓库。把导出的源码复制到Git工作目录里检查.gitignore然后git add、git commit。确认无误后旧目录就可以退出历史舞台了。切记不要在同一目录中通过反复删除.svn和.git来“强行修复”因为两套工具对本地状态都有自己的缓存删除后状态判定很容易错乱反而引发更多问题。6.4 跨工具协作的其他避坑建议还有一些问题不常被提到但“同时使用SVN和Git”的场景里特别容易踩。第一个是换行符规则。SVN的svn:eol-style可以指定文件的换行符风格Git则靠core.autocrlf和.gitattributes控制。如果同一个文件在两个库里的换行符规则不同提交日志里就会出现“整个文件都是被修改的荒唐状态”。统一建议是在Git仓库里用.gitattributes文件显式指定文本文件的换行符风格比如LF在SVN仓库里同样设置svn:eol-style为native或LF两边保持一致。第二个是文件权限。SVN里有一个svn:executable属性可以标记脚本文件是否需要可执行权限Git里则依赖文件系统的可执行位在Windows上往往不生效。如果你同时维护Linux部署用的脚本很容易出现“SVN里看起来正常、Git里丢了执行权”的情况。建议每次在Git仓库里添加新脚本时用chmod x设置可执行位并提交验证。第三个是提交粒度。SVN习惯把一批相关改动放在一次提交里Git虽然也推荐原子提交但分支合并时常常需要把多个commit压成一个。这两个习惯本身没有冲突但如果你一边用SVN同步代码、一边用Git管理自己开发分支很容易对不上版本号排查问题时难以快速定位。我的习惯是在SVN提交信息里写对应Git提交的部分hash在Git提交信息里写SVN的revision形成一个双向索引后期对照起来会省很多力气。第四个是安全问题。无论用SVN还是Git都要注意不要把.svn或.git目录暴露到外部可访问的路径上不要把账号密码硬编码进代码仓库也不要把个人私钥文件提交到仓库里。之前网上讨论过不少“.git目录泄露”或者“SVN目录泄露”的情况本质上都是运维疏忽把元数据目录当成了静态资源一并发布导致源码和版本历史整体暴露。作为开发者在手写nginx或IIS的静态目录发布时至少要把包含版本控制元数据的父目录排除干净构建产物目录里也不要复制.svn和.git。这不是什么高深技巧属于基本的安全习惯。7. 我的实操体会与额外小建议文章写到最后我想聊聊这几年同时维护SVN和Git的个人感受。工具说到底是要为流程服务的。“同时使用SVN和Git”这件事本身不难难得是让两套工具各归其位。我现在的准则是存量项目维护SVN老老实实该提交提交、该回滚回滚新项目和新需求一律走Git两套仓库之间不搞奇怪的双写同步只做必要的源码导入导出。这样听上去可能有点“保守”但实际用下来最稳定也最不容易在关键时刻出幺蛾子。如果你刚开始接触这个组合我建议新手先别急着把两个工具堆在一台机器上反复折腾可以先把目录分开SVN项目放D:/svn-workspaceGit项目放D:/git-workspaceSVN日常用TortoiseSVNGit尽量从Git Bash练起等两边都熟练了再去研究git svn桥接、跨仓库同步这类进阶玩法。最后再分享一个小技巧我习惯在SVN和Git两个仓库里都保存一份相同的README文件里面写着“本项目当前版本号、当前负责人、最近一次更新的时间”。每次大版本发布后手动同步一次这个文件。别小看这个笨办法当两边代码分叉厉害、一时又理不清谁是谁的时候这个文件就是最简单的“索引”能快速判断两边是否处于同一个节奏。对于长期并存的“双版本控制”项目这种低成本的对齐方式比想象中有用得多。
返回列表