Skip to content

什么是 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 addgit commit两个独立步骤。 add 决定"这次提交包含哪些内容",commit 决定"什么时候固化历史"。

快照,而不是差异(Git 与 SVN 的本质区别)

  • SVN 等系统存储的是文件之间的差异(diff):记录"这一行改成了什么"。
  • Git 存储的是快照(snapshot):每次提交都保存所有文件在那个时刻的完整状态。
text
SVN 视角:  v1 → v2(+3行) → v3(-2行) → ...
Git 视角:  v1(全量) → v2(全量) → v3(全量) → ...

Git 之所以不占太多空间,是因为它对内容做了压缩和去重:

  • 文件内容没有变化时,新快照直接复用旧文件对象(引用同一个对象)。
  • 只有真正改变的文件才会生成新的对象。

Git 的三个承诺

  1. 快(Fast):绝大多数操作在本地完成,无网络等待;核心操作经过极致优化。
  2. 分布式(Distributed):每个克隆都是完整仓库,离线可用。
  3. 数据完整性(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),但命令行是理解和排错的基础