---
epoch: 1781683778800
modelKey: deepseek-v4-flash|deepseek
tags:
  - copilot-conversation
topic: 版本控制笔记拆分
---

**user**: 将这份文件也请有逻辑地划分为多篇md文件以便更好理解，分布式版本控制系统可以有逻辑的添加双链和表且
[Context: Notes: 计算机系/版本控制系统.md]
[Timestamp: 2026/06/17 16:09:38]

**ai**: 好的，我来将这份《版本控制系统》笔记按逻辑拆分为多篇独立的 Markdown 文件。我会尽量保留原有知识密度，并适当添加 **双链**（`[[笔记名称]]`）和 **表格**，帮助更好理解和串联知识。同时针对你提到的“分布式版本控制系统可以加双链和表格”，我会在相关部分重点处理。

以下是拆分方案及每篇文件的完整内容。你可以直接在 Obsidian 中创建对应文件。

---

### 文件结构（存放在 `计算机系/版本控制系统/` 目录下）

```
计算机系/
└── 版本控制系统/
    ├── 版本控制概述.md
    ├── Git 核心概念与基础操作.md
    ├── 远程仓库与标签.md
    ├── Git 分支管理.md
    └── Git 内部原理.md
```

---

## 1. 版本控制概述.md

```markdown
# 版本控制概述

版本控制系统（Version Control System，VCS）让我们能够将选定的文件回溯到之前的状态，甚至将整个项目回退到过去某个时间点。我们可以比较文件的变化细节，查出最后是谁修改了哪个地方，从而找出导致怪异问题出现的原因。

## 集中式与分布式对比

| 特性 | 集中式（如 SVN、CVS） | 分布式（如 Git、Mercurial） |
|------|----------------------|----------------------------|
| 存储位置 | 单一中央服务器，保存所有修订版本 | 每个人电脑上都有完整仓库镜像（含历史） |
| 离线工作 | 需要联网才能操作 | 完全离线工作，推送时才需要网络 |
| 数据安全 | 中央服务器损坏且无备份，则丢失所有历史 | 任何一份本地仓库都可恢复全部历史 |
| 协作方式 | 从中央服务器取最新版 → 工作 → 推送 | 可互相推送，但常用“中央服务器”作为交换节点（如 GitHub） |
| 典型系统 | Subversion (SVN)、CVS | Git、Mercurial |

为了减小存储大小，分布式系统会使用压缩算法（如 Git 的 `git gc` 打包对象）。

> **扩展阅读**：[[Git 核心概念与基础操作]]、[[Git 内部原理]]

## 集中式（Centralized VCS）

集中式版本库集中存放于一个单一的中央服务器，保存所有文件的修订版本。协同工作时，人们需要先从中央服务器取得最新版本，然后开始干活，干完活了，再把自己的活推送给中央服务器。如果中心数据库所在的磁盘发生损坏，又没有做恰当备份，你将丢失所有数据——包括项目的整个变更历史，只剩下人们在各自机器上保留的单独快照。

## 分布式（Distributed VCS）

分布式版本控制系统根本没有“中央服务器”，每次是把代码仓库完整地镜像下来，包括完整的历史记录。这使得每个人的电脑上都是一个完整的版本库，不仅仅是最新版本的文件快照。

这么一来，任何一处协同工作用的服务器发生故障，事后都可以用任何一个镜像出来的本地仓库恢复。同时，也不需要联网就可以进行工作。

> 在实际使用分布式版本控制系统时，很少直接在两个人之间的电脑上推送修改（因为可能不在同一局域网）。因此，分布式版本控制系统通常也有一台充当“中央服务器”的电脑或服务器（如 GitHub），但这个服务器的作用仅仅是方便“交换”大家的修改，没有它大家也一样干活，只是交换修改不方便而已。这也是我们在 GitHub 建立 repo 的原因。

### Git 的额外优势

Git 默认保存文件**快照**而非差异，并且会存储全部历史版本和最新版本。关于 Git 如何高效存储，请参见 [[Git 内部原理]]。
```

---

## 2. Git 核心概念与基础操作.md

```markdown
# Git 核心概念与基础操作

## Git 快照的本质

Git 并不会像一些版本控制系统那样每次保存文件的完整副本（比如 Subversion）；相反，Git 会对文件的状态进行索引，利用**快照（snapshot）**来记录文件的内容。每次执行 `git commit` 时，Git 会将**暂存区（staging area）**中的文件状态保存为一个新的快照。

- 这个快照并不是直接存储文件本身，而是存储文件内容的哈希值。
- 具体来说，Git 对每个文件生成一个唯一的 **SHA-1 哈希值**，并通过这些哈希值来追踪每个文件的变化。

> Git 更像是把数据看作是对小型文件系统的一系列快照。如果没有修改，Git 不再重新存储该文件，而是只保留一个链接指向之前存储的文件。

## 初始配置

```bash
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
git config --list
```

## 基本工作流程

| 区域 | 说明 |
|------|------|
| 工作区（Working Directory） | 你实际修改文件的地方 |
| 暂存区（Staging Area / Index） | 临时保存即将提交的文件快照 |
| 本地仓库（Local Repository） | 提交后数据永久存储的地方 |
| 远程仓库（Remote Repository） | 共享与备份的 Git 服务器（如 GitHub） |

基本流程：**工作区修改 → `git add` → 暂存区 → `git commit` → 本地仓库 → `git push` → 远程仓库**

### 文件状态

| 状态 | 描述 |
|------|------|
| 未跟踪（Untracked） | 新文件，尚未被 Git 纳入版本控制 |
| 已跟踪（Tracked） | 已纳入版本控制，又分为： |
| → 未修改（Unmodified） | 文件内容与上次提交一致 |
| → 已修改（Modified） | 文件内容已变更，未放入暂存区 |
| → 已暂存（Staged） | 修改已加入暂存区，等待提交 |

## 常用命令速查表

| 命令 | 功能 |
|------|------|
| `git init` | 在当前目录初始化 Git 仓库 |
| `git clone <url>` | 克隆远程仓库到本地 |
| `git status` | 查看当前文件状态 |
| `git add <file>` | 将文件添加到暂存区（或开始跟踪） |
| `git commit -m "msg"` | 将暂存区内容提交到本地仓库 |
| `git diff` | 查看工作区与暂存区的差异 |
| `git diff --staged` | 查看暂存区与上次提交的差异 |
| `git log` | 查看提交历史 |
| `git log --oneline --graph` | 简洁图形化日志 |
| `git show <commit>` | 查看某次提交的具体内容 |
| `git rm <file>` | 从 Git 中移除文件（同时删除工作区文件） |
| `git rm --cached <file>` | 从跟踪清单中移除但仍保留工作区文件 |
| `git mv <old> <new>` | 重命名/移动文件 |
| `git checkout -- <file>` | 撤销工作区的修改（危险） |
| `git reset HEAD <file>` | 取消暂存（从暂存区移回工作区） |
| `git commit --amend` | 修改最近一次提交（合并到上次提交中） |

### 忽略文件（.gitignore）

创建一个 `.gitignore` 文件，列出要忽略的文件模式，例如：

```
*.log
build/
.DS_Store
```

关于更多细节，可参考 [[远程仓库与标签]] 和 [[Git 分支管理]]。

## 查看提交历史与回溯

```bash
git log --oneline -5                     # 最近5条提交
git log --since="2 weeks ago"            # 两周内的提交
git log --author="someone"               # 某作者的提交
git log -S "function_name"               # 包含特定字符串增删的提交
git reflog                               # 本地所有 HEAD 移动历史
git reset --hard HEAD^                   # 回退到上一个版本（丢弃工作区修改）
git reset --soft HEAD^                   # 回退版本但保留工作区和暂存区修改
git reset --mixed HEAD^                  # 回退版本并取消暂存（保留工作区修改）
```

> 谨慎使用 `git reset --hard`，它会丢弃所有未提交的更改。

## 子模块

通过 `git submodule add <url>` 添加子模块。子模块是独立的 Git 仓库，父仓库只记录其当前提交的 SHA-1。

```bash
git submodule update --remote   # 拉取子模块最新版本
git submodule status            # 查看子模块状态
```

## 打包（git bundle）

Git 可以将数据打包成一个二进制文件（`git bundle`），方便离线传输：

```bash
git bundle create repo.bundle HEAD master
```

> 关于远程操作和标签，请参阅 [[远程仓库与标签]]。
```

---

## 3. 远程仓库与标签.md

```markdown
# 远程仓库与标签

## 远程仓库管理

### 查看与添加远程仓库

```bash
git remote -v                            # 查看所有远程仓库
git remote add origin <url>              # 添加远程仓库（别名 origin）
git remote rm origin                     # 删除远程仓库
```

### 拉取与推送

| 命令 | 说明 |
|------|------|
| `git fetch origin` | 拉取远程仓库所有数据（不自动合并） |
| `git pull origin master` | 拉取并自动合并到当前分支（等效于 `fetch + merge`） |
| `git push origin master` | 将本地 master 分支推送到远程 |
| `git push origin --delete branchName` | 删除远程分支 |

### origin 与 master 的关系

- **origin**：远程仓库的默认别名。
- **master**：本地默认分支（现代 Git 可能默认 `main`）。
- **origin/master**：本地对远程仓库 master 分支的引用，表示远程状态。

```bash
git diff master origin/master            # 查看本地与远程的差异
```

关于分支的远程跟踪，请参见 [[Git 分支管理]]。

## 打标签

### 创建标签

```bash
git tag v1.0.0                           # 创建轻量标签
git tag -a v1.0.0 -m "Release 1.0"       # 创建附注标签（推荐）
git tag -l "v1.*"                        # 列出匹配模式的标签
```

### 推送与删除标签

```bash
git push origin v1.0.0                   # 推送单个标签
git push origin --tags                   # 推送所有标签
git tag -d v1.0.0                        # 删除本地标签
git push origin :refs/tags/v1.0.0        # 删除远程标签
```

## 撤销操作

| 场景 | 命令 |
|------|------|
| 修改上次提交（漏文件或写错信息） | `git commit --amend` |
| 取消暂存文件 | `git reset HEAD <file>` |
| 撤销工作区修改 | `git checkout -- <file>`（危险） |
| 回退到历史版本 | `git reset --hard <commit>` |

关于回溯的更详细说明，参见 [[Git 核心概念与基础操作#查看提交历史与回溯]]。
```

---

## 4. Git 分支管理.md

```markdown
# Git 分支管理

## 为什么需要分支

多人协同开发时，分支可以保证每个人的开发互不影响，等到稳定后再合并到主干。

## 基本分支操作

| 命令 | 说明 |
|------|------|
| `git branch` | 列出本地分支 |
| `git branch <name>` | 创建新分支（基于当前 HEAD） |
| `git checkout <name>` | 切换到指定分支 |
| `git checkout -b <name>` | 创建并切换到新分支 |
| `git branch -d <name>` | 删除本地分支（删除前需先合并到其他分支） |
| `git branch -D <name>` | 强制删除未合并的分支 |
| `git branch -m <old> <new>` | 重命名分支 |

## 合并分支

```bash
# 先切换到目标分支（如 master）
git checkout master
git merge feature-branch
```

### 合并冲突

当两个分支对同一文件的同一部分做了不同修改并提交时，Git 无法自动合并，会产生冲突。需要手动编辑冲突文件解决，然后：

```bash
git add <file>       # 标记为已解决
git commit
```

## 分支开发工作流建议

- **master 分支**始终稳定，仅用于发布版本。
- 开发在**短期分支**（如 `feature/*`、`bugfix/*`）中进行。
- 完成测试后合并回 master。
- 多使用分支，养成好习惯。

## 远程分支与跟踪

### 拉取远程分支

```bash
git fetch origin                      # 获取远程所有分支
git branch stable origin/stable       # 创建本地分支并跟踪远程分支
git checkout stable                   # 切换到 stable 分支（会自动跟踪）
```

### 推送改名的本地分支到远程

```bash
git branch -m oldBranch newBranch     # 本地重命名
git push origin newBranch             # 推送新分支
git push --delete origin oldBranch    # 删除远程旧分支
```

## 贮藏（Stash）

当需要切换分支但不想提交当前修改时使用：

```bash
git stash                             # 保存当前修改，工作区变干净
git stash list                        # 查看所有贮藏
git stash apply                       # 恢复最近一次贮藏
git stash drop                        # 删除最近一次贮藏
git stash pop                         # 恢复并删除
```

> 更详细的命令可参见 [[Git 核心概念与基础操作]]。
```

---

## 5. Git 内部原理.md

```markdown
# Git 内部原理

## Git 目录结构

一个 Git 仓库的 `.git` 目录大致如下：

```
.git/
├── config               # 本地配置（大小写敏感、远程仓库 URL 等）
├── description          # 仅供 GitWeb 使用
├── HEAD                 # 当前被检出的分支
├── index                # 暂存区信息
├── hooks/               # 钩子脚本
├── info/                # 包含全局排除文件 exclude
├── logs/                # 所有操作日志（reflog）
├── objects/             # 存储数据内容（对象）
│   ├── info/
│   └── pack/            # 打包文件
└── refs/                # 指向提交对象的指针
    ├── heads/           # 本地分支
    ├── remotes/         # 远程分支
    └── tags/            # 标签
```

## Git 对象

Objects 目录下存储三种核心对象：

| 对象类型 | 说明 | 示例 |
|----------|------|------|
| **blob**（数据对象） | 存储文件内容（不包含文件名） | 文件快照 |
| **tree**（树对象） | 存储文件名和目录结构，指向 blob 或子树 | 类似文件系统目录项 |
| **commit**（提交对象） | 存储提交信息（作者、时间、父提交、指向的 tree） | 一次 commit 记录 |

Git 通过 SHA-1 哈希值来标识每个对象，例如 `24b9da6552252987aa493b52f8696cd6d3b00373`。

## 打包与压缩

Git 最初向磁盘存储对象时采用“松散”对象格式；但为了节省空间，Git 会定期将多个对象打包成一个“包文件”（packfile）。触发打包的时机：

- 松散对象过多时自动执行 `git gc`
- 手动执行 `git gc`
- 向远程服务器推送时也会触发打包

## 引用（References）

Git 将一些常用的 SHA-1 值存储在文件中，用文件名替代，这些别名称为**引用**（refs）。三种引用类型：

- `refs/heads/` — 本地分支
- `refs/remotes/` — 远程分支
- `refs/tags/` — 标签

```bash
git reflog                          # 查看 HEAD 和分支的引用日志
git ls-remote origin                # 查看远程所有引用
```

> Git 的“快照”核心思想在 [[Git 核心概念与基础操作]] 中有详细说明。
```

---

### 双链与表格说明

- 每篇文件开头或结尾都使用了 `[[ ]]` 链接到相关笔记，方便在 Obsidian 中跳转浏览。
- 表格用于对比集中式/分布式、文件状态、常用命令、对象类型等，使信息一目了然。
- 在 `版本控制概述.md` 中重点用表格对比了两种类型，并添加了指向其他笔记的双链。

你可以直接将这些内容复制到对应文件中（文件路径按上述结构）。如果需要调整子目录名或文件名，请告诉我。
[Timestamp: 2026/06/17 16:10:28]