Git版本管理

Git 版本管理

[!abstract] 概述
Git 是一个==分布式版本控制系统==,用于追踪文件的变更历史,支持多人协作开发。本教程将帮助你理解 Git 的核心原理和基本用法。


一、为什么需要版本控制?

想象你在写一篇论文,你可能会这样备份:

论文.doc
论文_修改.doc
论文_最终版.doc
论文_最终版2.doc
论文_打死不改版.doc

[!warning] 问题

  • 文件越来越多,根本分不清哪个是最新的
  • 想找回之前某个版本?几乎不可能
  • 多人同时修改同一文件?冲突不断

版本控制系统(VCS) 就是来解决这些问题的。而 Git 是目前最流行的版本控制工具。


二、Git 的核心原理

2.1 三个区域

Git 的核心模型围绕==三个区域==展开:

graph LR
A["📁 工作区<br/>Working Directory"] -->|"git add"| B["📦 暂存区<br/>Staging Area"]
B -->|"git commit"| C["🗄️ 本地仓库<br/>Local Repository"]
C -->|"git push"| D["☁️ 远程仓库<br/>Remote Repository"]
D -->|"git pull / git fetch"| A
区域 说明 类比
工作区 你实际编辑文件的地方 你的书桌
暂存区 暂时存放即将提交的变更 打包好的快递箱
本地仓库 保存所有提交历史的地方 档案柜
远程仓库 团队共享的云端仓库 共享图书馆

[!tip] 记忆口诀
add 放进箱子 → commit 存进柜子 → push 送到云端

2.2 快照模型(Snapshots)

Git 和其他版本控制系统(如 SVN)最大的区别在于存储方式:

graph TD
subgraph "SVN:差异存储"
V1["版本1: 文件A完整内容"]
V2["版本2: 文件A的==差异=="]
V3["版本3: 文件A的==差异=="]
V1 --> V2 --> V3
end

subgraph "Git:快照存储"
S1["版本1: 文件A的快照"]
S2["版本2: 文件A的新快照"]
S3["版本3: 文件A的新快照"]
S1 --> S2 --> S3
end

[!note] 快照 vs 差异

  • 差异存储:只记录每次改了什么(像记流水账)
  • 快照存储:每次提交都保存文件的完整状态(像拍照片)
  • Git 实际上会对==未变化的文件保留指针==,只对变化的文件创建新对象,所以非常高效

2.3 对象模型

Git 底层用四种对象来存储所有数据:

对象类型 作用 说明
blob 存储文件内容 纯粹的数据,不含文件名
tree 存储目录结构 记录文件名和对应的 blob/tree
commit 存储提交信息 指向一个 tree,记录作者、时间、父提交
tag 存储标签信息 给某个 commit 起一个名字
graph TD
C1["commit v1"] -->|"tree"| T1["tree /"]
T1 -->|"README.md"| B1["blob: hello"]
T1 -->|"src/"| T2["tree src/"]
T2 -->|"main.py"| B2["blob: print..."]

C2["commit v2"] -->|"tree"| T3["tree /"]
T3 -->|"README.md"| B3["blob: hello world"]
T3 -->|"src/"| T2

C1 -->|"parent"| C2

[!info] 关键理解
每个对象都通过其内容的 ==SHA-1 哈希值== 来唯一标识。只要内容相同,哈希就相同,Git 就会复用该对象。这就是 Git 高效的秘诀。

2.4 分支的本质

[!success] 分支只是一个指针!
在 Git 中,分支本质上只是一个指向某个 commit 的==可移动指针==。创建分支几乎不消耗任何资源。

gitGraph
commit id: "提交1"
commit id: "提交2"
branch feature
checkout feature
commit id: "功能开发"
commit id: "功能完成"
checkout main
merge feature id: "合并"
commit id: "后续修改"

三、常用命令速查

3.1 初始化与配置

# 初始化仓库
git init

# 配置用户信息(首次使用必须设置)
git config --global user.name "你的名字"
git config --global user.email "你的邮箱"

# 查看配置
git config --list

3.2 基本工作流

# 查看当前状态
git status

# 将文件添加到暂存区
git add 文件名 # 添加指定文件
git add . # 添加所有修改

# 提交到本地仓库
git commit -m "提交说明"

# 查看提交历史
git log --oneline # 简洁模式

3.3 分支操作

# 查看分支
git branch

# 创建并切换分支
git checkout -b 新分支名
# 或使用新语法
git switch -c 新分支名

# 切换分支
git switch 分支名

# 合并分支
git merge 要合并的分支名

3.4 远程操作

# 关联远程仓库
git remote add origin 仓库地址

# 推送到远程
git push -u origin main

# 拉取远程更新
git pull

# 克隆仓库
git clone 仓库地址

3.5 撤销与回退

[!danger] 注意
回退操作会改写历史,在公共分支上请谨慎使用!

# 撤销工作区的修改
git checkout -- 文件名

# 取消暂存
git reset HEAD 文件名

# 回退到上一个版本(保留修改)
git reset --soft HEAD~1

# 回退到上一个版本(丢弃修改)
git reset --hard HEAD~1

# 查看所有操作记录(可找回丢失的提交)
git reflog

四、典型工作流程

4.1 个人开发流程

flowchart LR
A["编辑文件"] --> B["git add ."]
B --> C["git commit -m '说明'"]
C --> A
C --> D["git push"]

4.2 团队协作流程(Feature Branch)

flowchart TD
A["从 main 拉取最新代码"] --> B["创建 feature 分支"]
B --> C["开发功能"]
C --> D["提交代码"]
D --> E["推送到远程"]
E --> F["创建 Pull Request"]
F --> G["代码审查"]
G --> H["合并到 main"]

[!tip] 最佳实践

  • 每个功能/修复使用独立分支
  • 提交信息要清晰有意义
  • 频繁提交,小步前进
  • 合并前先拉取最新代码

五、.gitignore 文件

.gitignore 文件告诉 Git 哪些文件不需要追踪:

# 编译产物
*.class
*.o
build/

# 依赖目录
node_modules/
vendor/

# IDE 配置
.idea/
.vscode/
*.swp

# 系统文件
.DS_Store
Thumbs.db

# 敏感信息
.env
*.key

六、常见问题 FAQ

[!faq]- Git 和 GitHub 是什么关系?
Git 是版本控制工具(软件),GitHub 是托管 Git 仓库的网站(服务)。类似的平台还有 GitLab、Gitee 等。

[!faq]- 忘记提交到哪个分支了怎么办?
运行 git reflog 可以查看所有操作记录,找到对应的 commit hash 后用 git checkout <hash> 查看。

[!faq]- 代码合并冲突了怎么办?

  1. 打开冲突文件,找到 <<<<<<<=======>>>>>>> 标记
  2. 手动选择保留哪部分代码
  3. 删除标记符号
  4. git add 然后 git commit

[!faq]- 不小心 push 了敏感信息怎么办?
使用 git filter-branchgit filter-repo 工具清除历史记录,然后 force push。但要注意这会改写历史,需要通知团队成员。


七、学习资源


[!quote] 总结
Git 的核心思想:快照式存储 + 分布式协作。理解了三个区域(工作区、暂存区、仓库)和对象模型(blob、tree、commit),你就掌握了 Git 的精髓。