什么是 Git 与版本控制
本章要点
- 为什么需要版本控制:历史、回溯、协作
- 集中式 vs 分布式版本控制的区别
- Git 的三个核心区域:工作区、暂存区、版本库
- Git 的三大承诺:快、分布式、数据完整性
- 两个最重要的比喻:快照系统 与 时间机器
版本控制要解决什么问题
想象没有版本控制的开发场景:
text
文档_v1.doc
文档_v1_修改.doc
文档_v2_最终版.doc
文档_v2_最终版_真最终.doc
文档_v2_最终版_真最终_打死不改.doc这是一场灾难:文件爆炸、无法知道谁改了什么、更无法回到某个历史版本。
版本控制(Version Control) 系统解决了三个核心问题:
| 问题 | 版本控制的答案 |
|---|---|
| 忘记改了什么 | 自动记录每次修改的内容、时间、作者、说明 |
| 改坏了想回去 | 可以回到任意历史版本(时间机器) |
| 多人同时开发 | 各自在自己的分支上工作,互不干扰,最后合并 |
版本控制的历史与分类
第一代:本地版本控制(Local VCS)
把文件的补丁(diff)存在本机的一个数据库里,如 RCS。
- 优点:简单
- 缺点:只能单人使用,数据库损坏 = 一切丢失
第二代:集中式版本控制(Centralized VCS)
代表:CVS、Subversion(SVN)。
text
中央服务器(唯一权威)
/ | \
开发者A 开发者B 开发者C- 优点:集中管理,权限清晰,适合小团队
- 缺点:
- 单点故障:服务器挂了,所有人都无法提交
- 依赖网络:离线无法工作
- 服务器硬盘损坏 = 历史全部丢失(本地通常只有工作副本)
第三代:分布式版本控制(Distributed VCS)
代表:Git、Mercurial(Hg)。
text
仓库A(你) 仓库B(同事)
↕ 克隆 ↕ 克隆
远程仓库(GitHub / GitLab / 自建)- 每个开发者的本地都有一份完整的仓库,包含全部历史。
- 离线也能提交、查看历史、创建分支。
- 任何一份副本损坏,都可以从其他人那里恢复。
- 所谓"远程仓库"只是大家约定俗成的一个同步中心,并不是唯一权威。
Git 的诞生
- 2005 年,Linux 内核社区需要新的版本控制系统。
- Linus Torvalds(Linux 之父)用两周时间写出了 Git。
- 设计目标:快、简单、支持大规模分布式开发、数据完整性极强。
Git 的核心概念
三个区域(最重要的一张图)
text
┌─────────────┐ git add ┌─────────────┐ git commit ┌─────────────┐
│ 工作区 │ ──────────► │ 暂存区 │ ─────────────► │ 版本库 │
│ Working │ │ Staging │ │ Repository │
│ Directory │ │ (Index) │ │ (HEAD) │
└─────────────┘ └─────────────┘ └─────────────┘
↑ │
└──────────── git checkout / git restore ◄─────────────────┘| 区域 | 通俗理解 | 对应命令 |
|---|---|---|
| 工作区(Working Directory) | 你眼睛看到的、编辑器里正在编辑的文件 | — |
| 暂存区(Staging Area / Index) | 准备打包的"购物车",git add 把改动放进去 | git add |
| 版本库(Repository) | 历史档案库,git commit 把暂存区内容固化成永久快照 | git commit |
💡 一个关键认知:
git add和git commit是两个独立步骤。 add 决定"这次提交包含哪些内容",commit 决定"什么时候固化历史"。
快照,而不是差异(Git 与 SVN 的本质区别)
- SVN 等系统存储的是文件之间的差异(diff):记录"这一行改成了什么"。
- Git 存储的是快照(snapshot):每次提交都保存所有文件在那个时刻的完整状态。
text
SVN 视角: v1 → v2(+3行) → v3(-2行) → ...
Git 视角: v1(全量) → v2(全量) → v3(全量) → ...Git 之所以不占太多空间,是因为它对内容做了压缩和去重:
- 文件内容没有变化时,新快照直接复用旧文件对象(引用同一个对象)。
- 只有真正改变的文件才会生成新的对象。
Git 的三个承诺
- 快(Fast):绝大多数操作在本地完成,无网络等待;核心操作经过极致优化。
- 分布式(Distributed):每个克隆都是完整仓库,离线可用。
- 数据完整性(Integrity):所有对象都通过 SHA-1 哈希 校验(Git 2.30+ 起逐步转向 SHA-256)。内容只要被篡改,Git 立刻能发现。历史上没有任何人能在无人察觉的情况下改变 Git 仓库中哪怕一个字节的提交内容。
文件的状态
Git 眼中的文件只有四种状态:
text
untracked(未跟踪:新建的、从未 add 过的文件)
│ git add
▼
staged(已暂存:add 过,还没 commit)
│ git commit
▼
committed(已提交:进了版本库)
│ 修改文件内容
▼
modified(已修改:改过但还没 add)
│ git add
▼
staged(再次进入暂存区)……用 git status 随时查看当前状态。状态机是理解 Git 一切行为的基础。
两个帮助你理解的比喻
比喻一:Git 是一台时间机器
git commit= 存档点(记录那一刻的整个世界)git checkout <commit>/git restore= 回到某个存档点git log= 查看存档点列表- 分支 = 平行宇宙(多条时间线)
git merge/git rebase= 合并时间线
比喻二:提交(commit)是一张"拍立得照片"
text
commit = { 照片内容(所有文件的快照)
+ 拍摄时间
+ 摄影师(作者)
+ 照片说明(提交信息)
+ 上一张照片的编号(父提交) }每张照片都记得"我是从哪张照片拍出来的",于是所有照片串成了一条不可篡改的链条——这就是 Git 历史的结构。
Git 的完整工作流程总览
text
# 首次使用一个仓库
git clone <url> # 把远程仓库整个复制到本地
# 或者新建
git init # 在当前目录初始化一个空仓库
# 日常循环(第 3 章详解)
git status # 看看现在是什么状态
git diff # 看看改了什么(未暂存)
git add <文件> # 把改动放入暂存区
git diff --staged # 看看将要提交的内容
git commit -m "提交说明" # 固化一个快照
# 协作(第 5 章详解)
git push # 把本地提交推到远程
git pull # 拉取远程更新并合并
git fetch # 只拉取远程更新,不合并常见误区澄清
| 误区 | 真相 |
|---|---|
| "Git 就是 GitHub" | Git 是工具(版本控制系统),GitHub 只是托管 Git 仓库的网站之一(还有 GitLab、Gitee 等) |
| "提交到 Git 就安全了" | 只有 push 到远程仓库才真正"异地备份";本地 commit 在硬盘损坏时依然会丢 |
| "commit 越多越好" | 提交要小而完整、信息清晰,才利于回溯和 Code Review |
| "Git 只能命令行用" | 有大量图形界面(GitHub Desktop、VS Code、Sourcetree),但命令行是理解和排错的基础 |
