1. 先想清楚:这套“平台仓库 + Git + 两个小乌龟”到底解决什么问题
我见过太多人卡在这一步:代码写完了,想传到托管平台上,打开网页一看,满屏的git init、git remote、ssh-keygen,直接放弃;或者勉强传上去了,第二天队友改了同一个文件,一同步,代码全乱了,最后干脆改成“微信发压缩包 + 手动合并”。这个项目的标题其实就是在讲一件事——怎么用最省心的方式,把本地代码放到托管平台的仓库里,既能自己备份,又能和别人一起开发。核心关键词无非三个:仓库搭建、代码上传、多人协作,工具链是 Git 打底,Windows 上配 TortoiseGit 和 TortoiseSVN 这两套图形客户端。
先把话说透:这套方案不是“最优解”,而是“最不容易劝退的解”。纯粹的 Git 命令行当然更强大,但对一个刚接触版本管理的人来说,记住几十条命令的成本太高,而 TortoiseGit 把 90% 的日常操作变成了右键菜单——提交、拉取、推送、看日志、比差异、解决冲突,全在资源管理器里完成。TortoiseSVN 的存在则更微妙,它和 Git 不是替代关系,很多时候是历史遗留的 SVN 仓库还需要维护,或者团队里有人习惯了“更新—改—提交”这种线性思维,不想碰分支。
所以这篇内容适合三类人:一是第一次要把代码放到平台上做个人备份的,二是小团队三五个人要开始协作、但还没建立任何规范的,三是手上同时有 Git 仓库和 SVN 仓库、需要在同一台 Windows 机器上把两套工具都跑顺的。下面我按“方案怎么定 → 仓库怎么建 → 多人怎么配合 → 个人怎么备份 → 出问题怎么查”的顺序讲,每一步都给到可以直接照着敲的命令和界面路径。
1.1 三个需求拆开看:传代码、多人协作、个人备份其实是三件事
很多人把这三件事混为一谈,结果方案设计得很别扭。实际上它们的关注点完全不同,得分开设计。
传代码关注的是“首次成功”。你要解决的是仓库地址、认证方式、忽略文件、行尾换行符这几个坑,一次性配好,之后基本不用再碰。这一步的重点是别把不该传的东西传上去——编译产物、依赖目录、本地配置、密钥文件,一旦进了提交历史,想彻底清掉非常麻烦。
多人协作关注的是“长期不打架”。它需要的不只是工具,还有约定:谁改哪个分支、提交信息怎么写、合并前要不要过一遍评审、出现冲突谁来拍板。工具只能降低操作门槛,降低不了沟通成本。
个人备份关注的是“自动且可追溯”。它的核心诉求不是共享,而是“我三天前那版能跑通的代码还在不在”。这种场景下,本地频繁提交 + 定期推到远程 + 关键节点打标签,比什么都管用。
搞清楚这三点,你就明白为什么标题里既有 Git 又有 SVN 了:Git 适合分支密集、需要离线提交、需要精细历史记录的协作;SVN 适合目录权限严格、文件体积大、团队不想学分支模型的场景。两套东西各有各的地盘,强行统一反而添乱。
1.2 为什么是 TortoiseGit + TortoiseSVN,而不是只留一个
这个问题我被问过很多次。有人觉得装两个客户端太重了,其实从实际操作角度看,它俩共存几乎没有任何冲突,因为它们是两个独立的 Shell 扩展,右键菜单里各占一块,互不干扰。真正的风险点只有一个——千万不要在同一个目录里同时初始化 Git 仓库和 SVN 工作副本。.git文件夹和.svn文件夹放在一起,两个客户端都会试图接管这些文件的版本状态,结果就是状态显示错乱、提交漏文件、回滚回不干净。我踩过这个坑,一个项目目录里先后 checkout 了 SVN、又 git init,后来发现 TortoiseGit 把.svn里的文件也当成待提交内容了,差点把一堆内部元数据推上去。
具体分工我一般这么定:
| 场景 | 推荐工具 | 理由 |
|---|---|---|
| 新建托管平台仓库、日常提交推送 | TortoiseGit | 与平台仓库对接顺畅,分支操作图形化清晰 |
| 历史 SVN 仓库维护 | TortoiseSVN | 原生支持,避免用 git-svn 二次封装带来的怪问题 |
| 看某一行代码是谁改的 | TortoiseGit(Blame) | 逐行追溯,定位责任人和提交时间很快 |
| 大目录权限分级、只检出子目录 | TortoiseSVN | 支持稀疏检出,不用全量拉下来 |
| 个人项目备份 | TortoiseGit | 提交轻量、分支便宜、打标签方便 |
注意:如果一台机器上两个客户端都装了,建议把“图标覆盖”设置里的状态图标错开。TortoiseGit 和 TortoiseSVN 默认都想在文件图标上叠加绿色对勾、红色感叹号,Windows 的图标覆盖槽位只有十几个,装多了会互相挤掉,最后谁的状态都显示不全。
1.3 环境准备:装什么、装在哪、先配哪几项
落地之前先把环境理顺,能省掉后面一大半的玄学问题。我通常按这个顺序来:
- 先装 Git 本体。TortoiseGit 只是个外壳,底层还是调
git.exe,所以 Git for Windows 必须先装好,安装时把“Git from the command line and also from 3rd-party software”选上,保证 PATH 里有 git。 - 再装 TortoiseGit。安装过程中会让你选 SSH 客户端,默认用自带的 TortoiseGitPlink 就行,如果你打算用 OpenSSH 那套密钥,就选
ssh.exe。 - 最后装 TortoiseSVN。它自带命令行工具是可选项,建议勾上,方便脚本调用。
- 中文语言包按需装,装完在设置里切换语言并重启资源管理器。
装完第一件事不是建仓库,而是配身份。打开命令行:
git config --global user.name "你的昵称" git config --global user.email "你的邮箱" git config --global core.autocrlf true git config --global core.quotepath false git config --global init.defaultBranch maincore.autocrlf true这条在 Windows 上几乎是必配的。它的作用是:提交时把 CRLF 转成 LF 存进仓库,检出时再转回 CRLF。不配的话,同一个人在 Windows、另一个人在别的系统上,同一份文件会被判定为“整文件全改”,diff 一片红,评审根本没法看。core.quotepath false是让中文路径正常显示,不然git status里全是\344\275\240这种八进制转义。
TortoiseGit 里对应的设置路径是:右键 → TortoiseGit → Settings → Git,把 Name、Email 填上,AutoCrlf 选true。这一步和命令行配置是写同一份.gitconfig,两边改哪个都行。
2. 仓库搭建与首次上传:把“第一次成功”这件事做扎实
第一次推送成功带来的信心,比看十篇教程都管用。所以这一节我把动作拆到最细,包括平台上那几个容易被忽略的勾选项、.gitignore到底该写什么、以及首次推送报“非快进”该怎么处理。
2.1 建仓库时的四个关键勾选项
在托管平台上点“新建仓库”,界面大同小异,但有四个地方必须想清楚:
第一,仓库名和路径。名字用英文短横线分隔,别用中文和空格。路径一旦定下来,后面虽然能改,但所有本地仓库的 remote 地址都得跟着改,协作的人也要重新配,成本不低。
第二,公开还是私有。个人备份建议私有,多人协作按团队要求。私有仓库要注意成员权限,别一股脑全给管理员。
第三,要不要初始化 README。这里有个经典陷阱:平台上勾了“使用 README 初始化仓库”,远程仓库就有一个初始提交,而你本地也有提交,两边历史不相干,直接git push会报rejected - non-fast-forward。两种解法:一是建仓库时什么都不勾,得到一个空仓库,本地推上去最干净;二是先git pull --rebase origin main把远程那个初始提交拉下来,再推。
第四,.gitignore模板。平台上一般能直接选模板,选 Visual Studio、Python、Node 之类的对应项,它会自动生成一份忽略规则。这个很有用,但别全信,它不一定覆盖你项目里的特殊情况。
建完之后,页面上会给你两个地址:HTTPS 和 SSH。HTTPS 需要每次输账号密码(或者配凭证缓存),SSH 需要提前配好密钥。我的一般建议是:第一次上手用 HTTPS,跑通流程;长期用切 SSH,省得反复输密码。
2.2 本地初始化与.gitignore:这一步决定仓库干不干净
进到项目根目录,右键 → Git Bash Here,或者在 TortoiseGit 菜单里选 “Create repository here”。命令行版本:
cd /d/workspace/my-project git init git statusgit status会列出所有未被跟踪的文件。这时候先别急着git add .,先写.gitignore。一份典型的多语言项目忽略文件长这样:
# 依赖目录 node_modules/ venv/ .venv/ packages/ # 编译产物 bin/ obj/ dist/ build/ *.exe *.dll *.pdb # 编辑器与系统 .vs/ .idea/ .vscode/ *.user Thumbs.db .DS_Store # 本地配置与密钥 *.local .env appsettings.Development.json *.pfx *.pem写完之后git status再看一眼,确认那些目录已经不在列表里了。这里有个实操心得:.gitignore只对未被跟踪的文件生效。如果你已经git add了node_modules,再加忽略规则是没用的,得先git rm -r --cached node_modules把它从索引里摘出来,再提交一次。这一步很多人漏掉,结果仓库体积一下涨到几百兆,后面想瘦身非常痛苦。
提示:如果某个文件已经被跟踪,但你想让后续修改不再被提交(比如本地调试用的配置文件),可以用
git update-index --skip-worktree 文件名。它比--assume-unchanged更靠谱,尤其是在会切换分支的场景下。
2.3 首次提交与推送:两条路,选一条走通
命令行路线(推荐,出问题信息最全):
git add . git commit -m "chore: 初始化项目结构与忽略规则" git remote add origin https://你的平台地址/用户名/仓库名.git git branch -M main git push -u origin main-u的作用是把本地 main 和远程 origin/main 建立追踪关系,之后直接git push、git pull就行,不用再带参数。
图形界面路线:在项目目录右键 → Git Commit -> "master"... → 填提交信息 → 勾选要提交的文件 → Commit & Push。第一次会弹窗让你填远程地址和认证信息,填完保存即可。
两条路殊途同归,但有个细节值得说:首次推送如果被拒绝,八成是远程非空。报错信息里会出现Updates were rejected because the remote contains work that you do not have locally。这时候不要用git push -f去覆盖,覆盖会丢掉平台上那个初始提交,如果那不是你自己的仓库,还可能把别人的东西冲掉。正确做法是先合并:
git pull origin main --allow-unrelated-histories # 解决可能的冲突后 git push -u origin main--allow-unrelated-histories这个参数只在两边历史完全无关时才需要,正常协作中不需要加。
2.4 TortoiseGit 首次配置:三个容易忽略的设置项
图形客户端装完,有几个设置项建议一次性配好,不然会在很奇怪的地方卡住你。
网络认证:Settings → Git → Credential,把 credential helper 设成manager或者wincred,这样 HTTPS 方式输一次密码之后会被记住。SSH 方式则在 Settings → Network → SSH client 里指定ssh.exe的路径,并确保密钥已经加到平台的公钥列表里。
差异比较工具:Settings → Difftool,默认用 TortoiseMerge 就够用。它的三栏对比视图(本地、远程、合并结果)在解冲突时非常直观,比在命令行里盯着<<<<<<<舒服得多。
日志与作者显示:Settings → Log Messages,可以配提交信息模板。小团队统一一个模板,比如feat: xxx、fix: xxx、docs: xxx,后面看日志一眼就能分类。这不是形式主义,等仓库有两千条提交、你要找“半年前那个内存泄漏是哪次改的”,就知道规范的价值了。
3. 多人开发:工具解决不了沟通,但能把沟通成本降下来
多人协作里,工具只占三成,七成是约定。但工具配不好的话,那三成会放大成十成的痛苦。这一节讲怎么用 TortoiseGit 把日常协作动作变得可预期。
3.1 分支模型:小团队别学大厂那一套
我看到很多三五人的小团队,上来就搞 Git Flow:main、develop、feature、release、hotfix 五套分支。结果呢,develop 长期不合并,feature 分支活两周,最后合并时冲突堆成山,谁都不敢动。分支越多,合并成本越高,小团队根本扛不住。
我的建议是“主干 + 短分支”:
| 分支类型 | 命名 | 生命周期 | 用途 |
|---|---|---|---|
| 主干 | main | 长期 | 随时可发布的状态 |
| 功能 | feat/简短描述 | 1~3 天 | 单个需求或模块 |
| 修复 | fix/简短描述 | 几小时~1 天 | 线上问题或缺陷 |
| 个人 | dev/昵称 | 长期 | 个人实验,不参与合并 |
关键在短。功能分支活得越久,跟主干分叉越远,合并时冲突越多。所以我一般要求:一个分支不超过三天,做不完就拆成多个小分支,做完一个合一个。合并方式用git merge --no-ff,保留分支痕迹,日志里能看出“这块功能是一个整体”。
TortoiseGit 里创建分支:右键 → TortoiseGit → Create Branch,填名字,勾上 “Switch to new branch” 就直接切过去了。切换分支用 Switch/Checkout,注意切换前先提交或 stash,不然本地修改会被带过去,容易串味。
3.2 提交粒度与信息规范:写给三个月后的自己看
提交粒度这件事,说小了是习惯,说大了是团队的技术素养。我见过一个提交改三十个文件、提交信息写“修改”的仓库,后来查一个 bug 用了一整天,因为根本没法定位是哪次改动引入的。
几条硬规矩:
- 一次提交只做一件事。重构和改 bug 不要混在一起,格式化代码单独提一次。这样出问题时
git revert能干净回退,git bisect也能精准定位。 - 提交信息写“为什么”,不写“改了什么”。
git diff已经能看出改了什么,你要说明的是动机。比如不要写“修改登录逻辑”,改写“fix: 登录态过期后未清除本地缓存,导致重复跳转”。 - 提交前先看一眼 diff。TortoiseGit 的提交窗口下方就是差异预览,扫一眼有没有误改、有没有调试代码忘了删、有没有
console.log留在里面。
提示:如果本地改了太多东西,不知道怎么拆成多个提交,可以用
git add -p交互式暂存,一块一块地选。这个功能命令行才有,TortoiseGit 的提交窗口也支持按文件勾选,但做不到按代码块拆,遇到这种情况我会切回命令行。
3.3 冲突处理:从“看到红色就慌”到有条不紊
冲突的本质是“同一文件的同一位置被两边改了”。它不是错误,是正常的协作现象。真正的问题是很多人一看到冲突就手忙脚乱,随手选“用我的”或者“用他的”,把别人的改动冲掉了。
标准流程我一般这么走:
- 先拉再改。每天开工第一件事
git pull,改动前保证本地是最新的。这一步能消掉 80% 的冲突。 - 冲突发生时,先看状态。
git status会列出both modified的文件。 - 打开文件看标记。冲突区域会被
<<<<<<<、=======、>>>>>>>三段包裹,中间是两边的版本。 - 逐块决定保留哪边,或者手工融合。注意:很多时候正确答案不是“选 A”或“选 B”,而是把两边逻辑合起来。
- 删掉所有标记符号,保存。
- 标记为已解决:
git add 文件名,然后git commit完成合并。
TortoiseGit 的做法更直观:冲突文件图标是红色感叹号,右键 → TortoiseGit → Edit conflicts,会弹出 TortoiseMerge 三栏视图,左中右分别是你本地、合并结果、对方改动,点按钮就能把某一段拉过来。处理完点“Mark as resolved”保存。
如果搞砸了想重来:
git merge --abort # 放弃这次合并,回到合并前 git rebase --abort # 放弃变基 git checkout -- 文件名 # 丢弃单个文件的本地修改(慎用,不可恢复)还有一招救命用的:git reflog。它记录 HEAD 的每一次移动,包括合并、重置、变基。哪怕你reset --hard错了,只要没被垃圾回收,都能通过git reset --hard HEAD@{n}找回来。我用这招救回过至少三次误操作。
注意:
git checkout -- 文件名和git reset --hard都是不可逆的本地操作,执行前一定要确认没有未提交的重要改动,或者先git stash存一下。
3.4 图形界面里的合并、变基与回退
TortoiseGit 在主干的右键菜单里提供了一整套操作,用熟了比命令行快:
- Merge:把某个分支合进当前分支。勾选 “Squash” 会把对方所有提交压成一个,适合功能分支合并到主干,保持主干历史干净。
- Rebase:把你的提交“搬”到对方最新提交之后,历史是一条直线。适合个人分支同步主干,不适合已经推送到远程的公共分支(会让别人的历史错乱)。
- Reset:回退到某个提交。三种模式要分清——
Soft只移动 HEAD,改动留在暂存区;Mixed移动 HEAD 并取消暂存,改动留在工作区;Hard全部丢弃。日常最常用 Mixed。 - Revert:生成一个“反向提交”来抵消某次改动,适合已经推送的公共提交,因为它不改历史。
- Show log:按分支、作者、路径过滤历史,配合 Blame 定位到具体行。
这里补充一个协作约定:公共分支不要 rebase,不要 force push。这两件事会让别人的本地历史和远程对不上,轻则多一次合并,重则丢提交。真要整理历史,在自己没推过的分支上做。
4. 个人代码备份:把 Git 当成一台带版本的时间机器
个人备份是这套方案里最容易被低估的价值。很多人以为 Git 只是给团队用的,其实一个人写代码更需要它——你改崩了想回退、想对比昨天和今天的实现、想找“上周那个能用但被我删掉的函数”,全靠提交历史。
4.1 备份策略:三层,缺一不可
我把个人备份分成三层,从轻到重:
第一层,本地高频提交。改完一个能跑通的小节点就提交一次,不用等“全部做完”。提交是本地操作,不联网、不花钱、不影响别人,成本几乎为零。我自己的习惯是:功能能跑通提交一次,重构完提交一次,修完 bug 提交一次,下班前提交一次。
第二层,定期推送远程。本地提交只防“改错了”,不防“硬盘坏了”。每天收工前git push一次,让远程仓库有一份完整副本。这一步可以自动化,后面讲。
第三层,关键节点打标签。版本发布、论文投稿前、项目验收前,打个标签:
git tag -a v1.2.0 -m "稳定版本:核心功能完成,压力测试通过" git push origin v1.2.0 git push origin --tags # 一次性推所有标签标签和分支的区别在于:分支会移动,标签是钉子,钉死在某个提交上。半年后你想回到“当时交付给客户的那个版本”,标签是最快的入口。TortoiseGit 里在 Show log 窗口右键某个提交 → Create Tag here 就行。
4.2 自动化:一个脚本搞定每日备份
手动推送的问题是容易忘。我的做法是写一个小脚本,配合系统计划任务每天定时跑。Windows 下建一个backup.bat:
@echo off cd /d D:\workspace\my-project git add -A git commit -m "chore: 每日自动备份 %date% %time%" git push origin main echo 备份完成 %date% %time% >> D:\workspace\backup.log几个细节要注意:
git add -A会把所有改动(包括删除)加进去。如果项目里有不该提交的临时文件,说明.gitignore漏了,先把忽略规则补上。- 如果当天没有任何改动,
git commit会失败并返回非零状态码,脚本会中断。可以在提交前加个判断,或者用git commit -m "..." || echo 无改动容错。 git push可能因为网络或认证失败,脚本要记日志,别静默失败。我一般会让它把输出都重定向到日志文件,隔几天看一眼。- 定时任务建议设在午休或深夜,避开你在电脑前操作的时段,减少和手动操作撞车。
提示:自动提交会让提交历史变得很碎,几百条“每日自动备份”。如果想保持历史清爽,可以只在有实质改动时提交,或者把自动备份推到一个单独的备份分支(比如
backup/daily),主干保持干净。这是我用了一年多之后改的方案,效果明显好很多。
4.3 仓库体积:别让备份变成负担
备份做久了会遇到一个问题:仓库越来越大,克隆一次要十分钟。原因通常是两类文件——依赖目录和二进制大文件。
依赖目录(node_modules、venv、packages)绝对不能进仓库。它们体积大、文件多、可由配置文件完整重建,进仓库纯属浪费。检查方法:
git count-objects -vH # 看仓库体积 git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sort -k3 -n -r | head -20第二条命令列出仓库里最大的 20 个对象,能直接看出是哪个文件把仓库撑大的。
二进制文件(图片素材、设计稿、数据集、安装包)如果确实需要版本管理,用 Git LFS:
git lfs install git lfs track "*.psd" git lfs track "*.zip" git add .gitattributes.gitattributes要和代码一起提交,保证其他人克隆后也走 LFS。没装 LFS 的人克隆下来只会得到指针文件,这点要提前跟协作的人说清楚。
4.4 顺带说说 TortoiseSVN 在备份场景里的用法
如果你的历史资产在 SVN 仓库里,TortoiseSVN 有几个功能其实很适合备份场景:
Revision Graph(右键 → TortoiseSVN → Revision graph)能把分支、标签、合并关系画成一张图,一眼看出这个目录是怎么演化过来的。我在接手一个五年前的 SVN 项目时靠它理清了结构。
Show log 的过滤与导出:可以按作者、日期、路径过滤,还能把日志导出成 CSV,做项目统计很方便。
Revert 到某个版本范围:TortoiseSVN 的 “Revert” 支持合并式的反向修改,能把某几次提交的改动整体撤销,比 Git 的 revert 在面对连续多次提交时更省事。
锁定机制:SVN 的lock对二进制文件特别友好。两个人同时改一张设计图,Git 处理不了(没法自动合并 PSD),SVN 可以先锁再改,避免互相覆盖。这也是很多设计、文档类项目仍然用 SVN 的原因。
注意:SVN 的
update和 Git 的pull语义不同。SVN 的 update 是把服务器上的改动合并到工作副本,不会产生“合并提交”;提交时如果文件已被别人改过,会直接报冲突要你先更新。所以用 SVN 的团队要养成“改之前先 update”的习惯,比 Git 更依赖这个动作。
5. 常见问题与排查实录:这些坑我都替你踩过了
下面这些是我在实际操作中反复遇到的问题,按类型整理,附上排查思路。有些是配置问题,有些是理解偏差,都不难,但不知道的话能卡很久。
5.1 认证与权限类:推送被拒的六种可能
| 现象 | 可能原因 | 排查与解决 |
|---|---|---|
Permission denied (publickey) | SSH 密钥没配或没加到平台 | ssh -T 平台地址测试;检查~/.ssh/id_ed25519.pub是否已粘贴到平台 |
Authentication failed | HTTPS 密码错,或平台改用了令牌 | 用访问令牌代替密码;清理 Windows 凭据管理器里的旧记录 |
403 Forbidden | 账号对仓库无写权限 | 找仓库管理员加成员角色;确认推送的是自己的仓库还是别人的 |
remote: Repository not found | 地址拼错,或私有仓库无权限 | 逐字核对 remote 地址;git remote -v查看当前配置 |
| 每次都要输密码 | 未配 credential helper | git config --global credential.helper manager |
| 一台机器多个账号冲突 | 全局 user 配置被覆盖 | 用~/.ssh/config给不同 host 配不同密钥,仓库级单独设 user.email |
多账号的场景值得展开说。假设你有工作和个人两个身份,都在同一台机器上,做法是:
# ~/.ssh/config Host work-platform HostName 平台地址 User git IdentityFile ~/.ssh/id_work Host personal-platform HostName 平台地址 User git IdentityFile ~/.ssh/id_personal然后在各自仓库里设git remote set-url origin git@work-platform:组/仓库.git,再在仓库目录里单独执行git config user.email "工作邮箱"(不加--global)。这样两套身份互不干扰。
5.2 提交历史与文件状态类:历史被改了怎么办
问题一:提交了不该提交的文件。如果还没推送到远程,git reset --soft HEAD~1撤回提交,git rm --cached 文件,补.gitignore,重新提交。如果已经推了,就得用git revert生成反向提交,或者用历史重写工具清理——但重写历史会影响所有协作者,必须提前通知,让大家重新克隆。
问题二:切换分支后文件“消失”了。多半是那个文件在新分支上不存在,或者被.gitignore忽略了但之前是强制添加的。用git log --all -- 文件路径查它到底在哪些提交里出现过。
问题三:git status显示一堆莫名其妙的修改,但文件内容没变。九成是行尾换行符在作怪。检查git config core.autocrlf,Windows 上应该是true。还有一种可能是文件权限位变化,可以用git config core.filemode false关掉权限检测。
问题四:合并后代码编译不过,但两边单独都能编。这是典型的“语义冲突”——文本没冲突,逻辑冲突了。比如 A 改了函数签名,B 在新代码里还调用旧签名。这类问题工具发现不了,只能靠合并后跑一遍完整构建和测试。所以我的规矩是:合并主干后必须本地编译通过再推。
5.3 大文件、行尾、编码:三类顽疾的处理办法
大文件。前面提了 LFS,这里补充一个判断标准:单个文件超过 5MB 就该考虑要不要进仓库,超过 50MB 基本必须用 LFS 或者干脆放对象存储。仓库体积一旦涨上去,清理非常麻烦,因为 Git 的历史是不可变的,得用filter-repo这类工具重写全部历史,团队里每个人都要重新克隆。
行尾。除了core.autocrlf,更精细的控制写在.gitattributes里:
* text=auto *.sh text eol=lf *.bat text eol=crlf *.png binary *.jpg binarytext=auto让 Git 自动判断;shell 脚本强制 LF(不然在 Linux 上跑会报bad interpreter);批处理强制 CRLF;二进制文件标记为 binary 防止被当文本处理。
编码。中文注释在 Windows 上常见 GBK 和 UTF-8 混用,提交后 diff 全是乱码。解决办法是统一 UTF-8,并在编辑器里设默认编码。TortoiseGit 的 diff 窗口如果显示乱码,可以在 Settings → Diff Viewer → TortoiseMerge 里调整编码设置。另外core.quotepath false一定要配,不然中文文件名在命令行里根本认不出来。
5.4 两个客户端共存的注意事项
最后单独说一下 Git 和 SVN 在同一台机器上共存的问题,这是标题里明确提到的组合,实际用起来有几条纪律:
- 目录严格隔离。一个目录要么是 Git 仓库(有
.git),要么是 SVN 工作副本(有.svn),绝不混放。我一般是D:\git-workspace\和D:\svn-workspace\两个根目录分开。 - 图标覆盖错开。TortoiseGit 设置里可以把状态缓存关掉或者调整优先级,避免和 TortoiseSVN 抢图标槽位。
- 右键菜单会变长。两个客户端各加一堆菜单项,右键项目会很长。可以在设置里把不常用的项隐藏,只留 Commit、Update/Pull、Show log 这几个高频的。
- 不要用 SVN 客户端去碰 Git 仓库的目录,反之亦然。有些 SVN 的 “Check for modifications” 会递归扫描整个目录树,扫到
.git里的对象文件会卡很久。 - 备份脚本要区分。Git 的自动提交脚本和 SVN 的自动 update/commit 脚本分开写,别用同一套逻辑,两者的冲突处理机制完全不同。
6. 我个人的几条实操体会
用这套组合大概有几年了,说几个文档里不会写、但确实影响体验的点。
提交信息别偷懒。我知道自动备份脚本会生成一堆“每日自动备份”,但真正重要的提交,我一定手写信息。因为半年后回头看,能救你的不是代码本身,是那句“当时为什么这么改”。我现在的习惯是提交信息里带上下文,比如“fix: 分页参数在边界值下越界,因为前端传了 0 而没做兜底”。
分支要舍得删。合并完的功能分支立刻删掉,本地和远程都删。留着只会让分支列表越来越长,时间一长自己都分不清哪个是活的。删掉的提交不会丢,git log --all还能找到。
定期体检仓库。每个月跑一次git count-objects -vH和git gc --prune=now,看看体积有没有异常增长,顺手清理一下悬空对象。这跟给车做保养一个道理,小问题不处理,攒到某天克隆失败就麻烦了。
图形界面和命令行都得会一点。TortoiseGit 处理日常的百分之八九十操作很舒服,但遇到历史重写、复杂冲突、批量操作,命令行还是更快更准。我一般是图形界面做常规动作,命令行做“手术”。两者不是二选一的关系,是互补。
备份不等于协作。很多人把“推到远程”当成“备份完了”,其实远程仓库是共享的,别人可以改、可以删分支。真正重要的东西,除了推远程,我还会额外打一个标签,或者导出一份归档包放到别的地方。多一层冗余,成本很低,心里踏实。