一文读懂:Git、Github、GitLab、SVN(附:快速上手 Git,用 VSCode 操作 Git)
版本控制这个事儿,只要是写代码的,迟早都得面对。我刚入行那会儿,团队还在用 U 盘拷代码,一个文件能出现“最终版”“最终版2”“最终版打死不改”这种名字,现在想想都后怕。后来正式接触了 SVN,再到 Git,再配合代码托管平台,整个开发体验完全不一样了。不过对于刚接触这些概念的朋友来说,Git、GitHub、GitLab、SVN 这四个词摆在一起,确实容易懵:它们都是什么关系?到底该学哪个?先用哪个?
这篇文章我用一个从业者的实际视角,把这四个东西彻底讲明白,然后给你一条从零到上手 Git 的路径,并且全程用 VSCode 来操作,每一步都能直接照着做。无论你是刚转行、在校做实验、还是小团队里负责搭协作流程,这篇都适合你。
1. 核心概念拆解:这四个东西到底是什么
先说结论:这四个名词里,Git 和 SVN 是版本控制工具,GitHub 和 GitLab 是代码托管平台。工具管的是"怎么记录代码的变化",平台管的是"代码放在哪里、大家怎么协作"。这两层经常被混着说,所以很多新手会把 Git 和 GitHub 当一个东西,其实它们的关系更像"文件管理工具"和"云盘"的关系。
先建立一个最简单的认知框架:版本控制的核心需求有三个——记录历史、多人协作、备份恢复。围绕这三个需求,下面的工具各有各的做法。
1.1 Git:分布式版本控制系统
Git 是一个分布式版本控制系统,这句话里最重要的词是"分布式"。分布式意味着每个开发者电脑上都有一个完整的代码仓库历史,不只是代码的当前状态,还包括每一次提交的完整记录。你联网的时候可以把这些记录推送到远程服务器或者拉取别人的改动,不联网的时候你照样可以在本地提交、查看历史。
这种设计的直接好处是快。普通操作比如看历史、提交代码、切换分支,都是在本地完成的,不依赖网络。坏处也有,就是学习曲线相对陡峭一些,尤其对于从来没有用过任何版本控制工具的人。
关键特点:
- 几乎所有操作都在本地完成,速度快
- 分支(branch)是它的一等公民,创建和切换分支非常轻量
- 每个提交(commit)都是一次完整的快照,而不是单纯记录差异
- 是目前绝大多数公司和开源项目的事实标准
Git 是本文章的主角,后面你所有的代码管理、版本回退、多人协作,都是通过它完成的。
1.2 SVN:集中式版本控制系统
SVN 全称 Subversion,你把它理解成老一代的方案就行。它的核心逻辑是"集中式":所有代码集中存放在一台中央服务器上,开发者的电脑上只有当前工作的副本。每次要看历史记录、提交代码,都得上服务器去操作。
听起来很合理对吧?刚接触版本控制的人,往往会觉得 SVN 这种集中式的方式更符合直觉。我在老东家那边,有将近三年的时间都在用 SVN,当时的体验其实也还行,因为团队小,功能分支用得不频繁。但用熟了 Git 再回看 SVN,就能明显感觉到它的局限:网络慢的时候,看历史都卡;分支的代价很大,创建分支是在服务器端做目录拷贝,玩多了仓库很臃肿;本地没有完整历史,出差在飞机上想查个旧改动都没办法。
所以如果你现在问我要不要学 SVN,我的回答是:可以了解它的思想,但不建议投入太多精力。现在大多数新项目都已经从 SVN 迁移到 Git 了。这篇文章里讲 SVN,主要是让你知道它的存在,以及理解集中式和分布式的区别,因为你早晚会在各种资料里看到"集中式"这个词。
1.3 GitHub:面向开源和社区的代码托管平台
GitHub 是建立在 Git 之上的代码托管平台。你可以理解成它给 Git 仓库提供了一个"云端驻地",支持网页端浏览代码、提交 Issue(议题)、发起 Pull Request(合并请求)、做 Code Review(代码评审)、自动跑 CI/CD(持续集成和持续交付)工作流。
但是 GitHub 真正的价值,我认为是它构建了一个庞大的开源生态。数以百万计的开源项目都放在上面,你可以在里面找到任何你想找的代码库,可以直接把别人的仓库 fork 到自己名下,改完代码之后给原作者提交一个合并请求,只要对方审核通过,你的代码就能合并进原始项目里。这种"所有人参与所有人项目"的模式,是 Git 时代之前无法想象的。
GitHub 对于个人开发者也有很大的意义。你可以把它当成自己的代码存档和简历,把你做过的模拟项目、练习作品都传上去。面试的时候,直接把仓库链接发给对方,比口头描述有说服力得多。
1.4 GitLab:自托管和企业级协作平台
GitLab 和 GitHub 干的事情大体类似,也是基于 Git 的代码托管平台,同样提供仓库管理、Issue、代码评审、CI/CD 这些功能。最核心的区别是部署模式。
GitHub 是"软件即服务",你注册账号就能用,代码托管在它的服务器上。GitLab 则可以让你把整个平台部署到自己公司的内网服务器里,代码不出公司,安全和合规方面更有保障。很多对数据安全要求高的公司、金融行业、军工单位,都会选择自托管的 GitLab。
GitLab 的 CI/CD 能力也非常强,它内置的流水线(Pipeline)配置功能,可以让代码推送到仓库后自动触发编译、测试、部署的完整流程,很多团队选择 GitLab 就是冲着这点去的。
用一句话概括这四者的关系:Git 是工具,SVN 是工具,GitHub 是围绕 Git 的公有云平台,GitLab 是既可公有云也可私有化部署的 Git 平台。搞清楚这层关系之后,接下来的对比才有意义。
2. 深入对比:Git 和 SVN 的差异到底在哪
先放一个表格,把核心差异列出来,然后逐个详解。注意看"设计模型"这一行,这是两者最深层的区别。
| 对比维度 | Git | SVN |
|---|---|---|
| 设计模型 | 分布式 | 集中式 |
| 本地历史记录 | 完整保存 | 无 |
| 分支创建成本 | 极低,瞬间完成 | 较高,完整拷贝目录 |
| 大部分操作是否依赖网络 | 不依赖 | 依赖 |
| 学习曲线 | 较陡峭 | 较平缓 |
| 离线工作能力 | 完全支持 | 不支持 |
| 典型使用场景 | 现代开发、开源协作 | 遗留项目、老团队 |
2.1 提交模型:快照与差异
这里的核心差异,值得多花点时间搞清楚。SVN 的每一次版本记录,实际保存的是"这次改动和上一次的差异",是一个补丁文件。它的历史记录,是由一串连续的差异串接起来的。要看某一时刻的完整代码,只能沿着记录一直往回拼凑,这很依赖网络和服务器端的计算能力。
Git 则完全不同。你看 Git 提交记录的时候,它保存的不是差异,而是完整的代码快照。每一次 commit 都是当前所有文件的完整状态。文件没变的话,Git 会用链接指向之前已经保存过的相同内容,不会真的重复存储。这种"快照流"的存储方式让 Git 在切换分支、查看历史、对比版本时都异常迅速,因为这些操作本质上是在本地读取已经保存好的快照。
我举个例子:你开发到一半,发现改坏了,想回到两天前的状态。SVN 的做法是向服务器发起"回滚请求",服务器重新计算差异,把文件一点一点拼回去。Git 的做法是本地直接切换到那个快照,整个过程不到一秒。
2.2 分支与合并:Git 的杀手锏
SVN 也支持分支,但这个操作在 SVN 里是"重"的。你在 SVN 里创建分支,相当于在仓库里复制了一份完整目录,之后在主分支和分支之间来回合并,每次都要手动处理一堆目录级别的差异。所以很多 SVN 团队实际上是"用主干干活,不到万不得已不开分支",分支在这个体系里是奢侈品。
Git 的分支就完全是另一回事了。分支的本质其实就是一个指针,指向某一个 commit。你创建一条新分支,成本几乎为零,切换分支也就是移动一下指针加更新工作区文件。这让 Git 的研发流程有了质的改变:你可以为每个新功能开一个分支,做完了合并回主干,再删除分支。主干的代码永远是稳定的,谁都不会互相踩脚。
这种分支模型也会改变你写代码的方式。在 SVN 里,你总有一种"别搞乱别人的代码"的紧张感。在 Git 里,你可以大胆地在自己分支上做实验,哪怕改得一团糟,删掉重建就行,完全不污染主线。
2.3 离线能力与团队适应成本
离线工作的能力,是我从 SVN 切换到 Git 之后感受最明显的一点。以前用 SVN,在地铁上想查个之前删掉的函数都要连网;用 Git 之后,随时随地 git log、git diff、git show,全部秒回。
不过也要客观地说,Git 的学习曲线确实比 SVN 陡。SVN 的命令简单直观,checkout、commit、update,来回就这几个。Git 的话,你至少要理解工作区、暂存区、本地仓库、远程仓库这四个概念,命令也多了一圈,一不留神还会把文件丢在暂存区里忘了提交。
如果你现在是零基础,我的建议是不要绕开 Git,因为它值得你花这个时间去学。你可以边用边理解,不用一开始就背命令。
3. 平台选择:什么时候选 GitHub,什么时候选 GitLab
工具层面的问题解决之后,就该聊聊平台了。很多刚接触 Git 的人还搞不清仓库和平台的关系,这里再明确一下:Git 是一台安装在你自己电脑上的工具,而 GitHub 和 GitLab 是给别人访问的"展示柜"和"协作空间"。你的代码先在本地用 Git 管理,然后推送到远程平台上,别人才能看到和协作。掌握了这层关系之后,下面的平台选择思路就顺了。
3.1 开源项目和个人作品,首选 GitHub
如果你做的是开源项目,或者想把个人作品展示给别人看,选 GitHub 是默认答案。原因很简单:它拥有全球最大的开发者社区,搜索引擎收录好,别人搜索某个技术关键词,有很大概率在 GitHub 上找到你的项目。你提交的代码、提的 Issue、做的 Code Review,都会沉淀为你的公开履历。
GitHub 上还有一个很实用的机制叫 fork。你看中一个项目,想基于它做自己的修改,只需要点击 fork,就会在你自己名下生成一个副本,跟原始项目互不影响。改好了想回馈给原项目,就发起 Pull Request,作者审核通过后就能合并。这套流程就是开源协作的基础。
3.2 企业内部部署,优先考虑 GitLab
GitLab 最大的优势在于私有化部署。企业把 GitLab 部署在自己的服务器上,代码完全处于自己的掌控之中,不经过第三方平台。很多公司对代码安全极度敏感,或者有一些合规要求,不方便把代码放到公共平台,GitLab 就是这种情况下最合适的选择。
GitLab 的权限模型也设计得非常细,对于企业来说这很重要。你可以精确到"某个开发者在某个项目下某个分支上是否有推送权限",这对于大型团队和严格的管理流程来说,是不可或缺的能力。
3.3 选择时还需要考虑这些因素
平台选择没有绝对的对错,只看你的场景。我再列几个实际的考量点,你在决策时可以对照着看:
- 团队规模:三五个人用什么平台都无所谓,十几人以上就要考虑权限管理的复杂度。
- 网络环境:有些地区访问 GitHub 会感觉速度不太稳定,而 GitLab 如果是自托管的,不存在这个问题。
- 业务性质:纯开源项目放 GitHub 有天然优势,商业项目或受监管项目更倾向 GitLab。
- 团队既有技术栈:如果你已经在某个平台建立了自动化流水线,迁移成本要提前算清楚。
有一种常见的组合是:公开的项目和个人作品放 GitHub,公司的私有项目用公司内部部署的 GitLab。这样既享受了开源社区的生态,又兼顾了企业内部的安全合规要求,一举两得。
4. 快速上手:在 VSCode 中完整操作 Git
前面讲了不少理论,下面进入实战。我选择用 VSCode 来讲,因为它是目前最主流的代码编辑器之一,内置的 Git 功能强大到足以覆盖日常 90% 的需求,而且图形化界面比命令行更直观,特别适合新手入门。
在开始之前,先把要准备的环境列出来。你需要有:一台能联网的电脑、VSCode(目前最新版即可)、Git(安装后就是后面说的操作基础)、以及一个 GitHub 或 GitLab 账号(没有的话用本地仓库的方式也能先练手)。接下来我们一步步来。
4.1 环境准备:安装 Git 并完成基础配置
你用 VSCode 操作 Git 之前,电脑上必须先安装 Git 本体,因为 VSCode 只是一个"壳",真正的版本控制能力还是由 Git 提供的。安装过程本身很简单,在官网下载对应系统版本的安装包,一路 Next 安装完成即可。
装好之后,第一步要设置你的身份信息。打开 VSCode 的终端(快捷键 Ctrl + `,在菜单栏"终端"里也可以打开),执行下面两条命令:
git config --global user.name "你的名字" git config --global user.email "你的邮箱"这两条命令配置的是 Git 的提交人信息。每次你提交代码的时候,Git 都会把这两个信息记录到历史里。很多新手没配就直接提交,结果提交历史里显示的是让人一头雾水的系统默认名字,后面改了也影响历史记录的完整性。
检查配置是否生效,可以执行:
git config --global --list如果显示了刚才设置的名字和邮箱,说明一切正常,可以开始下一步了。
4.2 第一个 Git 仓库:初始化、提交、查看历史
从零开始创建 Git 仓库是最直观的场景。现在假设你在本地已经有一个项目文件夹,里面放了一些源代码文件。打开 VSCode,用"文件"->"打开文件夹"把这个项目文件夹加载进来。
左侧边栏找到源代码管理图标(长得很像一个分叉的枝桠),点击之后你会看到一个空的状态,VSCode 会提示你"初始化仓库"或者在终端里执行命令来初始化。代码仓库就是 Git 用来追踪文件变化的数据结构,它以一个隐藏文件夹的形式存在于你的项目目录里,平时不需要去动它,Git 会自动维护。
我习惯直接在终端里执行:
git init执行完你会发现,源代码管理面板里多了好多文件列表。这些文件都是当前工作区里的文件,它们处于"未跟踪"状态,意思是 Git 还没开始记录它们的变化。
提交一个文件需要两步:先把文件加入暂存区,再提交到仓库。在 VSCode 里操作时,你会看到文件列表的每一项后面都有一个加号图标,点击加号,文件就进入暂存区了。如果你想直接全部暂存,点击文件列表上方的"暂存所有更改"按钮即可。
暂存完成之后,在输入框里写一句提交说明,然后点击"提交",第一个 commit 就完成了。提交说明尽量写清楚这次改了什么,不要写"update"这种没意义的文字,因为将来你回看历史时,靠的就是这些说明文字。
如果想看看现在仓库里有哪些历史记录,在源代码管理面板上方有三个点(更多操作),点击后选择"提交"->"查看提交历史"即可。你会看到每条提交的作者、时间、消息,一目了然。
4.3 分支操作:创建分支,并行开发,合并回主干
分支是整个 Git 体系中我最推荐你优先掌握的能力。在 VSCode 中操作分支非常方便。
先看当前分支。VSCode 最底部状态栏会显示当前分支名,比如 main 或 master。点击它就可以打开分支面板。
创建一个新分支的步骤:
- 点击状态栏底部的分支名称,会弹出分支命令面板
- 选择"创建新分支"
- 输入分支名,比如
feature/login - 回车之后,VSCode 会为你创建新分支并自动切换过去
从现在开始,你在这个分支上提交的所有代码都属于新功能,不会影响主分支。你可以放心大胆地写,写错了直接重来也不怕。
完成新功能开发之后,把代码并回主干的流程是这样的:
- 首先确保你的改动已经提交到 feature 分支。在源代码管理面板里完成提交,确保状态栏显示"分支已发布"之类的信息(本地分支没有推送远程的话,状态可能显示"未推送",不影响接下来的操作)。
- 点击底部状态栏的分支名,切换到主分支 main。
- 分支名字旁边有一个分支图标,点击它展开更多操作,选择"合并分支"。
- VSCode 会弹出一个分支列表,让你选择要把哪个分支合并进来。选择刚才的
feature/login分支。
如果代码没有冲突,合并就自动完成了。如果出现冲突,VSCode 会把冲突文件标红,打开文件后你会看到类似这种标记:
<<<<<<< HEAD 这里是主分支上的代码 ======= 这里是 feature 分支上的代码 >>>>>>> feature/login冲突标记非常好辨认。上方是当前分支的代码,下方是待合并分支的代码。你只需要手动决定保留哪部分,删掉这两对标记,然后保存文件。之后重新提交一次合并记录就行。
提示:解决冲突时不要想着"两边都留就完了"。你要思考的是这个代码的最终表现形式,而不是机械地把两个版本拼在一起。很多时候两边的逻辑需要重写融合,而不是拼接。
4.4 远程仓库:克隆、推送、拉取
本地操作练熟之后,就要跟远程仓库打交道了。下面以 GitHub 为例来说,GitLab 的操作流程几乎一样。
先去 GitHub 网站上创建一个空仓库,这个动作是在网页上完成的。创建的时候注意不要勾选仓库初始化时添加 README 文件的选项,否则后面会有一次无谓的合并冲突。
在 VSCode 里克隆仓库到本地的步骤:
- 打开 VSCode 的欢迎页面(如果没打开,用快捷键 Ctrl + Shift + P 输入"欢迎"即可找到)。按快捷键 Ctrl + Shift + P。
- 在弹出的命令面板输入"Git: 克隆"并回车。
- 粘贴你仓库的 HTTPS 地址。
- 选择存放代码的本地文件夹,等待克隆完成。
克隆完之后,VSCode 会自动打开这个项目。你在这个本地仓库里做的任何提交,默认都只会保存在本地,push 的动作需要手动触发。在源代码管理面板顶部,你会看到一个"推送"按钮,点击即可把本地的提交记录推送到远程 GitHub 仓库。
反之,如果远程仓库有别人推的新代码,你需要点击源代码管理面板顶部的"拉取"按钮,把远程新提交拉下来和本地合并。
推拉的时机有个经验规律:每天开始工作前先拉取一次,每天结束之前把所有提交都推上去。最简单也最安全。
还有一个概念叫"拉取请求"(Pull Request)或"合并请求"(Merge Request)。这个东西在 VSCode 里看不到,它发生在网页端:你把自己的功能分支推送到远程之后,在 GitHub 网页上发起一个 PR,请求把 feature 分支合并到 main 分支。这是团队协作中最常见的代码审查方式,也是我强烈建议你尽早养成的习惯——代码合并前有人 review 一下,能挡住大量低级错误。
4.5 用 .gitignore 文件管理不想提交的文件
在实操过程中,你一定会有一些不想纳入版本控制的文件,比如 node_modules 这种依赖目录、.env 文件(里面往往有数据库密码等敏感信息)、临时输出文件、IDE 配置文件等等。如果这些文件被提交进了 Git 仓库,后续会带来各种头疼的问题。
解决办法是在项目根目录创建.gitignore文件,告诉 Git 哪些文件或目录不要追踪。下面是一个比较通用的示例:
# 依赖目录 node_modules/ dist/ build/ # 环境变量文件 .env .env.local # 系统文件 .DS_Store Thumbs.db # IDE 配置 .vscode/ .idea/需要注意,.gitignore只对尚未被 Git 追踪的文件生效。如果一个文件已经被纳入版本控制,再往.gitignore里面写它就来不及了,需要先执行git rm --cached取消追踪。这个事听起来简单,但很多新手都会踩进去,所以值得单独提出来。
5. 实操心得:日常 Git 流程与避坑指南
估摸一下,已经写了不少了,但最核心的实战经验还没完全铺开。Git 用久了你会发现,功能本身并不难,坑都藏在细节里。这里把我自己在实际开发中积累的一些高频场景、错误和解决思路整理出来,希望能帮你省下一些折腾的时间。
5.1 我习惯的日常开发循环
先说我平时通常怎么组织一天的工作流。这个流程用好之后,基本不会出大问题:
- 开始新功能前,先拉取主分支最新代码,确认自己当前的分支是基于最新代码创建的功能分支;
- 功能开发中,按逻辑切分成多个小提交,每个提交只做一件事,提交信息写清楚改了什么;
- 功能完成之后,先用测试和构建检查一遍,再推送到远程分支;
- 在网页端发 PR,请求别人审查代码,等审查通过后合并;
- 最终要回到主分支,拉取最新代码,再开始下一个功能。
这套流程的优点在于:主干代码永远保持高质量,每个功能的变更在合并之前都被审查过,出问题的时候可以通过分支定位到人、定位到改动范围。你可能会觉得流程繁琐,但团队协作越正规,这套流程的价值就越大。
5.2 三条救命命令:撤销与恢复
每个 Git 用户都经历过"糟了"的时刻。我把平时最高频的三种误操作和对应的解决方式列出来:
场景一:提交完了才发现提交说明写错了
git commit --amend -m "正确的提交说明"这个命令会把上一个提交替换为新的提交。注意,如果这个提交已经推送到远程,不能用这种简单方式处理,因为远程可能已经有别人依赖它了。没推送的话随便用。
场景二:把改动提交到了错误分支
# 先撤销提交但保留改动(软撤销,--soft 表示保留暂存区内容) git reset --soft HEAD~1 # 切回正确的分支 git checkout correct-branch # 重新提交 git commit -m "正确的提交"这里的原理可以理解为:把最近一次提交"摘下来",但这次改动本身还在工作区里,不会丢。接着换到正确分支,重新做一次提交即可。
场景三:本地改乱了,想恢复成和远程一模一样
git fetch origin git reset --hard origin/main注意:
reset --hard的威力很大,本地未推送的提交和未提交的改动都会被直接删掉,操作之前务必三思。如果本地有想保留的内容,先备份或者用git stash暂存起来。这个命令我建议只在本地确实完全乱掉、不需要保留任何改动的时候使用。
5.3 常见问题速查表
我把自己在带新人过程中,最常被问到的几个问题和解决办法整理成一张表。建议你收藏或者打印出来,遇到问题的时候对着看。
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 提交后显示"您的分支领先 X 个提交" | 有改动在本地但还没推送到远程 | 点击推送按钮,或执行git push |
| 推送到远程时被拒绝了 | 远程有新提交,本地落后了 | 先拉取远程再推送:git pull --rebase |
| 文件莫名其妙消失了 | 可能是恢复到了某个旧版本或切换了分支 | 用git reflog找到操作记录,切回正确位置 |
| 解决冲突后又搞乱了 | 手动修改冲突时删错了内容 | git merge --abort终止合并,重新从头来 |
| 不小心提交了不想提交的文件 | 暂存区里混入了不需要的文件 | 用git rm --cached 文件名取消追踪,加到 .gitignore |
| 找不到之前提交的某个版本 | 分支回退过,旧提交暂时丢了 | git reflog找到旧提交的哈希值,用git cherry-pick找回 |
这些都是我在实际工作中真正碰到过、也帮同事处理过的问题,不是从文档里抄的。用 Git 的时间久了你会发现,绝大多数问题都有对应的命令和解决思路,真正麻烦的从来不是工具本身,而是协作流程里的沟通。
5.4 关于学习路径的一点建议
如果你已经看到了这里,说明你确实想把这套东西搞明白。按照我的经验,比较顺的学习顺序是:
第一步,先照着这篇文里的操作流程,在本地自己建一个模拟项目 X 的文件夹,完成 init、commit、branch、merge 这些基本操作。不要一上来就碰远程仓库,先让本地玩顺畅。
第二步,注册一个 GitHub 账号,创建一个公开的练习仓库,把模拟项目 X 推上去。感受一下 push、pull 的远程协作流程,多试几次不丢人。
第三步,找一个开源项目(比如你经常用的某个库),顺着它的 README 看它的分支模型和贡献指南,理解真实项目怎么用 Git。如果想深入研究,可以 fork 下来,自己试着修复一个文档错误甚至提一个 PR。
最后一步,当你需要跟别人协作时,再去看团队规定的 Git 工作流(比如常见的功能分支、Git Flow、主干开发等模型)。这些模型本身的细节并不复杂,它们是基于不同的发布频率和团队规模演化出来的。
我自己踩过几次坑之后,现在对 Git 的态度很明确:它不是一个需要你背命令的工具,而是一种需要你理解设计理念的工作方式。理解了设计理念,所有的命令不过是在调用你脑子里的那个模型罢了。