最近工作中又用到了SVN,很多年前用过,现在更生疏了,重新梳理下跟Git的区别,相对来说Git比SVN更熟练些,通过Git的一些操作来重新理解SVN的常用操作。
一、核心理念差异
SVN(集中式版本控制):
- 只有一个中央仓库,所有操作都直接与中央仓库交互
- 没有本地仓库概念,commit直接提交到服务器
- 需要网络连接才能进行大多数操作
Git(分布式版本控制):
- 每个开发者都有完整的本地仓库(包含完整历史)
- commit提交到本地仓库,push才同步到远程
- 大部分操作可在本地完成,不需要网络
二、对应操作详细对比表
| 功能 | Git 操作 | SVN 操作 | 说明与差异 |
|---|---|---|---|
| 首次获取代码 | git clone [url] |
svn checkout [url] [path] |
都是完整下载代码,Git会复制整个仓库历史 |
| 更新代码 | git pull = git fetch + git merge |
svn update |
Git先获取远程变更再合并,SVN直接更新工作副本 |
| 提交更改 | 三步: 1. git add 2. git commit 3. git push |
一步:svn commit |
Git有暂存区和本地提交概念,SVN直接提交到服务器 |
| 查看状态 | git status |
svn status |
都显示文件状态,但Git显示更详细(分工作区/暂存区) |
| 查看修改 | git diff |
svn diff |
都可以查看未提交的修改 |
| 查看日志 | git log |
svn log |
Git日志功能更强大,有图形化选项 |
| 撤销修改 | git checkout -- [file] git restore [file] |
svn revert [file] |
都是放弃工作区的修改 |
| 撤销暂存 | git reset HEAD [file] |
无对应操作 | SVN没有暂存区概念 |
| 完全回退 | git reset --hard HEAD |
svn revert -R . |
恢复到最后一次提交/更新的状态 |
三、重要概念对应关系
1. 工作流程对比
Git工作流:
工作区 → git add → 暂存区 → git commit → 本地仓库 → git push → 远程仓库
SVN工作流:
工作副本 → svn commit → 中央仓库 → svn update ← 其他开发者
2. 冲突处理机制
- Git:在pull或merge时检测冲突,需要手动解决后重新add和commit
- SVN:在commit或update时检测冲突,解决后标记为已解决
- 两者都需要手动编辑冲突文件,但Git的冲突解决更灵活(可在本地测试)
3. 分支管理的差异
| 操作 | Git | SVN | 区别 |
|---|---|---|---|
| 创建分支 | git branch [name] git checkout -b [name] |
svn copy [源URL] [新URL] svn switch [新URL] |
Git分支是轻量级的指针,SVN分支是目录拷贝 |
| 合并 | git merge [branch] |
svn merge [源URL] |
Git合并更智能,支持三方合并 |
| 删除分支 | git branch -d [name] |
svn delete [分支URL] |
Git删除本地分支,SVN删除服务器分支 |
四、补充扩展内容
1. Git特有而SVN没有的功能
bash
# 1. 暂存区操作
git add -p # 交互式暂存(部分提交)
git stash # 临时保存未提交的修改
git stash pop # 恢复暂存的修改
# 2. 重写历史
git rebase # 变基,重写提交历史
git commit --amend # 修改最后一次提交
# 3. 高级日志查看
git log --oneline --graph --all # 图形化显示分支历史
git log -p filename # 查看文件的详细修改历史
# 4. 二分查找
git bisect start # 二分法查找引入bug的提交
git bisect bad # 标记当前版本有问题
git bisect good # 标记某个版本正常
2. SVN特有而Git没有的功能
bash
# 1. 部分检出(sparse checkout)
svn checkout --depth=immediates URL # 只检出顶级目录
svn update --set-depth=infinity dir # 后续完全检出某个目录
# 2. 目录权限控制
# SVN可以对目录设置精细的读写权限
# 3. 原子提交
# SVN的commit是原子的,要么全部成功要么全部失败
3. 常用对应命令详解
查看文件修改历史:
bash
# Git查看文件历史
git log --follow -p file.txt # 查看文件完整历史,包括重命名
git blame file.txt # 逐行查看谁修改的
# SVN查看文件历史
svn log -v file.txt # 查看文件提交历史
svn blame file.txt # 逐行查看(类似git blame)
忽略文件配置:
bash
# Git: 项目根目录的.gitignore文件
echo "*.log" >> .gitignore
echo "/temp/" >> .gitignore
# SVN: 需要设置svn:ignore属性
svn propset svn:ignore "*.log" .
svn propset svn:ignore -F .svnignore .
4. 实际工作流对比示例
场景:修复bug并提交
Git方式:
bash
git checkout -b fix-bug-123 # 创建并切换到新分支
# 修改代码...
git add . # 添加到暂存区
git commit -m "修复bug 123" # 提交到本地
git push origin fix-bug-123 # 推送到远程
# 创建Pull Request等待review
SVN方式:
bash
svn copy ^/trunk ^/branches/fix-bug-123 -m "创建分支"
svn switch ^/branches/fix-bug-123
# 修改代码...
svn commit -m "修复bug 123" # 直接提交到服务器分支
# 完成后合并回主干
svn merge ^/branches/fix-bug-123
svn commit -m "合并bug修复"
五、迁移注意事项
如果从SVN迁移到Git,需要注意:
- 历史迁移 :使用
git svn命令可以导入SVN历史 - 忽略文件转换:SVN的svn:ignore需要转换为.gitignore
- 工作习惯调整:开发者需要适应本地提交和分支的概念
- 权限管理差异:Git的权限控制通常通过服务器端实现(如GitLab、GitHub)
六、选择建议
选择Git的情况:
- 需要离线工作
- 频繁创建/合并分支
- 需要更灵活的本地工作流
- 开源项目协作
选择SVN的情况:
- 严格的目录权限控制需求
- 项目结构简单,不需要复杂分支
- 团队习惯集中式工作流
- 二进制文件较多(Git需配合LFS)
七、最佳实践小贴士
- Git:经常fetch查看远程变化,在本地commit之前先pull
- SVN:提交前先update,避免冲突
- 两者通用:提交信息要清晰明确,说明修改内容和原因
- 两者通用:不要提交编译生成的文件、配置文件中的密码等敏感信息
通过以上对比可以看出,虽然Git和SVN在操作上有许多对应关系,但由于架构设计的根本差异(分布式vs集中式),在使用理念和工作流程上有显著不同。理解这些差异有助于根据项目需求选择合适的工具。