# 版本控制工具
# 原始的版本控制
纯手工的版本控制:修改文件,保存副本
—— 保存副本名随意,不能辨别每一版的修改内容
# 版本控制的起源:diff & patch
- diff: 比较两个文件或者目录的差异,保存成一个差异文件(比如 diff.txt)
diff -u left right
- patch: patch 是 diff 的反向操作,使用差异文件对原始文件进行修改,生成新的文件
patch 可以通过 diff.txt+left 推算出 right,或者通过 diff.txt+right 推算出 left
patch left.c diff.txt
patch -R right.c diff.txt(-R 表示反向操作)
# RCS: 最早的本地版本控制工具
RCS 把 diff 的集合用 RCS 自己的格式存储起来,保存到磁盘中
1 | diff -n left.c right.c |
# CVS & SVN: 集中式版本控制工具
CVS: 第一个被大规模使用的版本控制工具
—— 不支持原子化操作、网络传输效率低
SVN: 优化了服务器上内容的存储、原子操作
—— 延迟高
集中式版本控制工具的问题:
- 狭窄的提交通道:提交排队,不能同时修改。提交缺乏质量控制;缺乏代码门禁,(解决方式 Rietveid 旁路检查)
- 数据安全性差:单点故障、黑客攻击
# git: 分布式版本控制工具
集中式 vs 分布式:记录差异还是记录快照
集中式版本控制工具以文件变更列表的方式存储信息
git 以快照的方式存储信息,每次保存时为当时的所有文件制作一个快照并保存快照的索引。如果文件没有修改,则不重新存储该文件,只保留一个链接指向之前存储的文件
集中式(如 CVS)——「脆弱的中央库」
| 维度 | 问题 |
|---|---|
| 可靠性 | 单点故障风险高 → 备份极其重要 |
| 性能 / 协作 | 所有操作需连服务器;受限于带宽;无法离线办公 |
| 安全性 | 假设服务器安全 → 实际易受单点故障、黑客攻击 |
| 适用场景 | 小型封闭项目(强调集中管理),不适合开源项目 |
分布式(如 git)——「健壮的分布式库」
| 维度 | 优势 |
|---|---|
| 架构 | 全是服务器(每个克隆即完整仓库)→ 无单点故障 |
| 操作体验 | 提交 = 本地操作 → 快、离线可用、编码不中断;支持移动办公 |
| 数据完整性 | 所有对象用 SHA1 哈希唯一标识;提交可 PGP 签名防篡改 |
| 工作模型 | 强调个体贡献 → 天然适配开源协作(分支、合并、Pull Request) |
SVN 不适合:跨地域的协同开发、对代码质量要求高的项目、开源项目
git 不适合:word 等二进制文档的版本控制(因为二进制文件在每次保存后,整个文件内容都会被重写),读授权无法精确到目录级别(解决:版本库按照目录划分)
git:极快的速度、简单的设计、对非线性开发模式的强力支持(允许成千上万个并行开发分支)、完全分布式、有能力高效管理像 Linux 内核一样的超大规模项目(速度和数据量)
# 安装配置
- Linux 下安装 Git 可以通过系统的包管理器安装,也可以通过下载源码编译安装。
- Windows 下使用 Git 有两种不同的方案:Git 原生安装包与图形化界面工具 TortoiseGit。
- 通过 Git 的配置命令,我们可以对个人身份、文本换行符、编码显示等进行配置。
# 基本使用
工程区域:版本库 (.git)、工作区、暂存区
文件三种状态:已提交、已修改、已暂存
- 准备
- git init project_name/ git clone url
如果包含二进制文件,克隆时使用 git lfs clone url
- 新增、删除、移动
- git add: 提交到暂存区
- git rm: 从版本库和工作区中删除文件
- git mv: git mv old_file new_file 可以重命名
- 查看工作区
- git diff: 比较两个版本之间的差异
- git status: 查看工作区和暂存区的状态
- 提交
- git commit: 提交暂存区到版本库
- 查看日志
- git log: 查看提交日志
- 推送到远程仓库
- git push: 推送到远程仓库 git push origin main
- 分支管理
- 查看本地分支:git branch
- 查看远程分支:git branch -r
- 查看所有分支:git branch -a
- 新建分支:git branch new_branch
git checkout -b new_branch 新建并切换分支 - 删除分支:git branch -d old_branch (-D 强制删除)(-r 删除远程分支,删除之后需要 push)
- 切换分支:git checkout branch_name (-f 强制切换)
- 拉取:git pull origin remote_branch:local_branch (如果名字一样只要写一个)
- 合并分支
git getch 拉取但不会自动合并
- 分支合并:git merge branch_name 从指定分支合并到当前分支
- 撤销操作
git rebase branch_name 将当前分支的修改移到指定分支的后面
- 撤销操作:git reset commit_id (–hard/–soft/–mixed)
git checkout -filename 撤销工作区修改
# 基本推送提交
略
# 本地分支合并
git merge: 两个节点合并到一个节点,保留两条分支的历史记录
git rebase: 将一个分支的修改移到另一个分支的后面,形成一条线性的历史记录,会造成 commit 节点不清晰,不建议在公共分支上使用
# 本地基本分支与节点更新
git pull
git fetch
# 冲突处理
略
# Fork & Merge Request
Fork: 在远程仓库上复制一个项目的副本,拥有独立的版本库,可以自由修改
Merge Request: 将 Fork 的修改提交到原始仓库,等待原始仓库的管理员审核
# issue
issue: 创建一个任务,用于追踪一个 bug 或者一个需求,GitHub、Gitee、GitLab 都支持 issue