# Git团队协作指南：从入门到精通

> **作者**：刘航宇（河南工业大学人工智能协会）
> **面向读者**：有一定编程基础，需要团队协作参赛的同学
> **代码语言**：Python为主
> **预计阅读时间**：60分钟
> **更新日期**：2026年4月23日

---

## 第一章：引言——为什么比赛团队需要Git？

### 1.1 场景引入：从一场灾难说起

想象这样一个场景：你和两个队友正在准备一场重要的比赛——中国大学生计算机设计大赛。你们分工明确：小明负责后端开发，小红负责前端界面，你负责算法优化。项目是一个智能数据分析系统，需要在4周内完成初赛作品。

比赛开始的第一周，你们斗志昂扬。小明每天把代码打包发给你们，小红在群里说"我改了main.py，你们注意一下"，你也在自己的电脑上继续优化算法。

然后，灾难开始降临。

**周一早晨**，小明发现小红的修改覆盖了他上周写的后端接口。原因是小红在本地文件上直接编辑，没有做任何记录。所有人都不知道最终版本是哪个，"小明说的那个版本在哪？"

**周三下午**，你花了两天优化了一个算法，但合并到小明的代码时，整个系统崩溃了。你想恢复到优化前的状态，但已经太晚了——你没有做任何备份。

**周五晚上**，比赛提交前一天，小红发现她的界面配色完全乱了。查了半天，发现是小明前天改的一个CSS文件影响的。没有人知道谁改了什么，什么时候改的，为什么要改。

最后，你们勉强拼凑出一个能跑的作品，但代码质量堪忧，技术文档也残缺不全。省赛结果出来，意料之中——没有晋级。

**这个故事每天都在各个大学的比赛团队中上演。** 问题的根源是什么？不是能力不足，不是时间不够，而是**缺乏有效的团队协作工具和流程**。

### 1.2 没有版本控制时的典型问题

在团队项目中，没有使用Git等版本控制系统时，会遇到以下典型问题：

```
❌ "我写的代码去哪了？"
   问题：文件被覆盖，无法恢复之前的版本
   
❌ "这版本怎么跑不动了？"
   问题：环境不一致，依赖版本冲突
   
❌ "小明改了我的代码！"
   问题：多人同时编辑同一文件，产生冲突
   
❌ "最终版本到底是哪个？"
   问题：版本混乱，不知道哪个是最新的
   
❌ "能恢复上周的代码吗？"
   问题：没有历史记录，无法追溯
```

这些问题不仅存在于比赛中，在日常的项目开发中也极为常见。更糟糕的是，在比赛的高压环境下，这些问题会被放大十倍。

### 1.3 Git登场：版本控制的革命

2005年，一个芬兰程序员Linus Torvalds（没错，就是发明Linux的那位大神）创造了Git。Git是一个**分布式版本控制系统**，它的设计目标就是解决团队协作中的版本控制问题。

**Git的核心特性**：

**1. 本地仓库**
```
Git的魔力在于：每个开发者的电脑上都有一份完整的代码仓库。
这意味着你可以：
- 在没有网络的地方工作
- 查看完整的提交历史
- 尝试各种修改而不影响他人
- 随时回退到任何历史版本
```

**2. 快照而非差异**
```
传统版本控制（如CVS、SVN）保存的是文件的变化（diff）
Git保存的是每个时刻的完整"快照"

这就像：
- SVN：记录每次修改的"补丁"
- Git：给每个时刻拍一张"照片"

好处：查看历史更快，恢复更快，数据更安全
```

**3. 强大的分支管理**
```
Git的分支轻如鸿毛。
你可以：
- 随意创建分支，互不干扰
- 轻松合并不同分支的代码
- 尝试新功能，失败了可以一键删除分支
- 管理多个版本的并行开发
```

### 1.4 为什么比赛团队必须使用Git？

对于参加比赛的团队来说，Git不仅是开发工具，更是**团队的命脉**。

**团队协作的价值**：

```
✅ 分工明确：每人负责不同模块，互不干扰
✅ 版本管理：每个阶段都有清晰的版本标记
✅ 回溯能力：任何时候都能恢复到之前的版本
✅ 代码审查：通过Pull Request检查队友的代码
✅ 备份保障：代码保存在远程服务器，不怕丢失
```

**针对比赛场景的价值**：

```
📌 省赛/国赛作品迭代
   初赛 → 复赛 → 决赛，每个阶段都有版本记录
   
📌 团队分工
   前端、后端、算法、文档，不同人在不同分支开发
   
📌 代码审查
   队长可以审核队员提交的代码，保证质量
   
📌 紧急回退
   出现问题时，快速回退到稳定版本
```

想象一下，如果你的团队使用Git：

- 每天早上`git pull`，就能获取队友昨天的最新成果
- 每人一个功能分支，互不干扰，完成了再合并
- 每次提交都有记录，"谁在什么时候改了什么，为什么改"
- 省赛提交版本打上标签，决赛优化再开新分支
- 即使电脑坏了，代码还在远程仓库

**这就是Git能给你的：有序、可追溯、安全的团队协作。**

### 1.5 学习目标

通过本篇文章，你将掌握：

```
📚 理论知识
   - Git的核心概念和设计思想
   - 工作区、暂存区、版本库的关系
   - 分支管理的原理
   
💻 命令操作
   - Git基本命令：add、commit、push、pull
   - 分支操作：创建、切换、合并、变基
   - 解决冲突的方法和技巧
   - 标签管理和版本发布
   
🤝 团队协作
   - Pull Request流程
   - 代码审查的方法
   - Git Flow工作流
   - 比赛项目的最佳实践
```

无论你是第一次参加比赛的新手，还是想提升团队协作能力的老手，这篇文章都能帮助你建立扎实的Git使用技能。

### 1.6 本章小结

本章中，我们了解了：

1. **典型灾难场景**：没有版本控制时，团队协作会遇到的四大问题
2. **Git的诞生**：Linus Torvalds在2005年创造了Git
3. **Git的核心特性**：本地仓库、快照存储、强大分支
4. **比赛团队的价值**：分工明确、版本管理、回溯能力、备份保障

下一章，我们将深入理解Git的核心概念，包括工作区、暂存区、版本库的关系，以及文件的各种状态。

---

## 第二章：基础概念——理解Git的核心思想

### 2.1 Git的三大工作区域

理解Git的第一步，是搞清楚它的三大工作区域：**工作区（Working Directory）**、**暂存区（Staging Area）**、**Git仓库（Repository）**。

这三个区域的关系，可以用下图表示：

```
┌─────────────────────────────────────────────────────┐
│                    你的电脑                          │
│                                                     │
│  ┌──────────────┐    git add    ┌───────────────┐  │
│  │              │  ───────────→  │               │  │
│  │   工作区      │               │   暂存区       │  │
│  │ Working Dir  │               │ Staging Area │  │
│  │              │  ←───────────  │   (Index)    │  │
│  └──────────────┘   git reset   └───────┬───────┘  │
│                                         │          │
│                                         │ git commit│
│                                         ↓          │
│                                 ┌───────────────┐  │
│                                 │               │  │
│                                 │  Git仓库      │  │
│                                 │ Repository    │  │
│                                 │               │  │
│                                 └───────────────┘  │
│                                                     │
└─────────────────────────────────────────────────────┘
```

**工作区（Working Directory）**

工作区是你电脑上的项目文件夹。在这一区域，你可以自由地创建、编辑、删除文件。它就像你的工作台，工具和材料都摆在这里。

```
工作区的特点：
- 实际存储项目文件的位置
- 可以随意修改，不影响Git记录
- 修改后需要通过git add添加到暂存区
```

**暂存区（Staging Area）**

暂存区是Git的一个特殊区域，位于`.git/index`文件中。它像一个"准备区"，存放着下次提交要包含的文件快照。

```
暂存区的特点：
- 精确控制要提交的内容
- 可以选择性地添加文件的部分修改
- 是工作区和Git仓库之间的缓冲地带
- git add命令将工作区的修改放入暂存区
```

**Git仓库（Repository）**

Git仓库是Git的核心数据库，存储着所有的项目历史。它位于项目根目录下的`.git`文件夹中（这是一个隐藏文件夹）。

```
Git仓库的特点：
- 包含所有的提交记录
- 记录了每个分支的信息
- 保存了文件的完整快照
- .git文件夹就是Git仓库本身
```

### 2.2 文件的生命周期

在Git中，每个文件都会处于以下四种状态之一：

```
未跟踪(Untracked) → 已跟踪(Tracked)
                      ↓
                已修改(Modified)
                      ↓
                已暂存(Staged)
                      ↓
               已提交(Committed)
```

**四种文件状态详解**：

**1. 未跟踪（Untracked）**

新创建的文件，还没有被Git管理。在`git status`中显示为"Untracked files"。

```powershell
# 查看状态
git status

# 输出示例：
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#   new_feature.py    ← 这个文件是新建的，还没有被Git跟踪
```

**2. 已修改（Modified）**

已跟踪的文件被修改了，但还没有放入暂存区。

```powershell
# 修改已跟踪的文件
# 编辑 new_feature.py

git status

# 输出示例：
# Changes not staged for commit:
#   modified:   new_feature.py    ← 这个文件被修改了，但还没暂存
```

**3. 已暂存（Staged）**

修改的文件已经通过`git add`添加到暂存区，等待下一次提交。

```powershell
git add new_feature.py

git status

# 输出示例：
# Changes to be committed:
#   modified:   new_feature.py    ← 已经添加到暂存区
```

**4. 已提交（Committed）**

文件已经通过`git commit`保存到本地仓库，形成一个历史快照。

```powershell
git commit -m "feat: 添加新功能"

git status

# 输出示例：
# nothing to commit, working tree clean    ← 工作区是干净的
```

### 2.3 Git的对象模型

Git是如何存储数据的？理解这个问题能帮助你更好地使用Git。

Git使用四种主要对象来存储数据：

**Blob对象**

Blob（Binary Large Object）存储文件的内容。每个文件的每个版本都是一个独立的Blob对象。

```python
# 假设你有一个Python文件
# 文件内容：print("Hello World")

# Git会为这个内容创建一个Blob对象
# Blob = 文件内容的二进制快照
```

**Tree对象**

Tree对象存储目录结构。它包含多个指向Blob和其他Tree的引用。

```python
# 假设项目结构：
# project/
# ├── main.py
# ├── utils.py
# └── config/
#     └── settings.py

# Git会创建：
# 1. main.py → Blob对象
# 2. utils.py → Blob对象
# 3. settings.py → Blob对象
# 4. config/ → Tree对象（包含settings.py的引用）
# 5. project/ → Tree对象（包含所有文件的引用）
```

**Commit对象**

Commit对象是整个系统的核心。它包含：
- 指向Tree对象的引用（项目在该时刻的快照）
- 指向父Commit的引用（上一个提交）
- 作者和提交者的信息
- 提交时的描述信息

```python
# Commit对象的内容（简化版）
{
    "tree": "abc123...",      # 项目快照的Tree对象
    "parent": "def456...",    # 上一个提交
    "author": "小明 <xiaoming@example.com>",
    "committer": "小明 <xiaoming@example.com>",
    "message": "feat: 添加用户认证功能"
}
```

**Tag对象**

Tag对象用于标记特定的Commit，通常用于标记发布版本。

```python
# Tag对象
{
    "object": "abc123...",     # 指向某个Commit
    "type": "commit",
    "tag": "v1.0.0",
    "tagger": "小明 <xiaoming@example.com>",
    "message": "第一个正式发布版本"
}
```

**为什么了解这些？**

理解Git的对象模型能帮助你：

```
✅ 理解为什么Git如此高效
   - 相同内容的文件只存储一次
   - 每个对象都有唯一的SHA-1哈希值
   - 查看历史非常快速

✅ 理解Git的完整性保证
   - 任何修改都会改变哈希值
   - Git能检测出任何文件损坏
   
✅ 在高级操作中游刃有余
   - 理解rebase、cherry-pick等操作的原理
```

### 2.4 远程仓库的概念

Git是分布式版本控制系统，这意味着每个开发者的电脑上都有完整的仓库。但为了让团队成员之间共享代码，我们需要一个"中央服务器"——这就是远程仓库。

**本地仓库 vs 远程仓库**

| 特性 | 本地仓库 | 远程仓库 |
|------|---------|---------|
| **位置** | 你的电脑 | 服务器（GitHub/Gitee等） |
| **用途** | 日常开发和提交 | 团队共享和备份 |
| **操作** | `git commit` | `git push/pull` |
| **网络要求** | 无需网络 | 需要网络连接 |
| **所有权** | 完全可控 | 团队共享 |

**常见的远程仓库服务**：

**1. GitHub（国际最流行）**
```
优点：
- 全球最大的代码托管平台
- 开源项目丰富
- 功能完善，社区活跃

缺点：
- 国内访问速度慢
- 私有仓库有限制

适合：开源项目、国际合作
```

**2. Gitee（码云，国内首选）**
```
优点：
- 国内访问速度快
- 私有仓库免费
- 中文界面

缺点：
- 国际访问较慢
- 功能比GitHub稍少

适合：国内团队比赛项目
```

**3. GitLab**
```
优点：
- 支持自建服务器
- 功能强大
- CI/CD集成好

缺点：
- 需要自己维护服务器

适合：企业、团队自建
```

**4. Coding（腾讯云）**
```
优点：
- 国内速度快
- 与腾讯云服务集成

缺点：
- 使用人数相对较少

适合：快速原型、小团队
```

**本地和远程的交互**：

```powershell
# 克隆远程仓库到本地
git clone https://gitee.com/team/competition-project.git

# 这时你的本地有两个仓库：
# 1. 本地仓库：完整的历史记录
# 2. 远程仓库：origin，指向Gitee上的仓库

# 日常工作流程：
# 1. 本地提交：git commit
# 2. 推送到远程：git push origin main
# 3. 获取队友更新：git pull origin main
```

### 2.5 理解SHA-1哈希

Git中的一切都由SHA-1哈希值标识。这个40位的十六进制字符串看起来像这样：

```
abc123def456abc123def456abc123def456abc1
```

**哈希值的作用**：

```
✅ 唯一标识：每个对象都有唯一的哈希值
✅ 内容寻址：相同内容产生相同的哈希
✅ 完整性保证：任何修改都会改变哈希值
✅ 不可猜测：无法从哈希值推断内容
```

**哈希值的实际使用**：

```powershell
# Git中经常使用哈希值的前几位来引用提交
git log --oneline

# 输出示例：
# abc123d feat: 添加用户认证
# def456e fix: 修复登录bug
# 789ghij init: 项目初始化

# 你可以使用缩写：
git show abc123d
git diff abc123d..def456e
git reset --hard abc123d
```

**为什么重要？**

理解SHA-1哈希能帮助你理解Git的核心原理：

```python
# Git对象存储原理
对象内容 + 类型 + 大小 → 计算SHA-1哈希 → 存储为文件名

# 这意味着：
# 1. 相同内容 = 相同哈希 = 只存储一次（节省空间）
# 2. 任何修改 = 哈希变化 = Git能检测到
# 3. 哈希是内容的指纹 = 完整性保证
```

### 2.6 本章小结

本章中，我们深入理解了Git的核心概念：

```
📚 三大工作区域
   - 工作区：实际编辑文件的地方
   - 暂存区：准备提交的文件快照
   - Git仓库：存储完整历史的地方

📝 四种文件状态
   - 未跟踪：新文件，还没被Git管理
   - 已修改：已跟踪文件被修改
   - 已暂存：修改已加入暂存区
   - 已提交：已保存到仓库

🏗️ Git对象模型
   - Blob：文件内容
   - Tree：目录结构
   - Commit：提交快照
   - Tag：版本标记

🌐 远程仓库
   - GitHub、Gitee、GitLab等
   - 本地和远程的交互：push/pull
```

下一章，我们将开始实战操作，学习Git的基本命令。

---

## 第三章：实战入门——Git基本操作

### 3.1 安装与初始配置

**安装Git**

在Windows上安装Git非常简单：

```powershell
# 方法一：下载安装包
# 访问：https://git-scm.com/download/win
# 下载并运行安装程序

# 方法二：使用winget（Windows包管理器）
winget install Git.Git

# 方法三：使用Scoop（你已经在用Scoop）
scoop install git
```

安装完成后，打开PowerShell或Git Bash，验证安装：

```powershell
# 检查Git版本
git --version

# 输出示例：
# git version 2.40.0.windows.1
```

**Python环境准备**

为了演示方便，我们需要一个Python环境：

```powershell
# 检查Python版本
python --version
# 确保有Python 3.6+

# 创建演示项目目录
mkdir git-tutorial
cd git-tutorial
```

**Git初始配置**

使用Git前，需要设置你的身份信息。这很重要，因为每次提交都会记录你的信息：

```powershell
# 设置用户名（必须）
git config --global user.name "你的名字"

# 设置邮箱（必须）
git config --global user.email "your.email@example.com"

# 查看所有配置
git config --list

# 输出示例：
# user.name=刘航宇
# user.email=3364451258@qq.com
# core.editor=code --wait
# init.defaultbranch=main
```

**配置参数说明**：

```
--global vs 本地配置

--global（全局）：
- 作用于当前用户的所有项目
- 配置文件在 ~/.gitconfig（用户主目录）

不加--global（项目级）：
- 只作用于当前项目
- 配置文件在 .git/config

建议：用户信息使用--global，其他可用项目级配置
```

**编辑器配置**

推荐使用VS Code作为Git的默认编辑器：

```powershell
# 设置VS Code为默认编辑器
git config --global core.editor "code --wait"

# 其他常见编辑器设置
# Vim
git config --global core.editor vim

# Notepad++
git config --global core.editor "notepad++ -multiInst -nosession"
```

### 3.2 初始化仓库

Git仓库是你项目的版本控制容器。有两种方式创建仓库：

**方法一：从头创建新仓库**

```powershell
# 创建项目目录
mkdir my-competition-project
cd my-competition-project

# 初始化Git仓库
git init

# 输出：
# Initialized empty Git repository in D:/projects/my-competition-project/.git/

# 查看所有文件（包括隐藏文件）
ls -la

# 输出示例：
# drwxr-xr-x 2 user 4096 Apr 23 10:00 .
# drwxr-xr-x 2 user 4096 Apr 23 10:00 ..
# drwxr-xr-x 3 user 4096 Apr 23 10:00 .git    ← Git仓库目录
```

`git init`命令做了以下事情：

```
✅ 创建 .git 目录
✅ 初始化Git仓库的基本结构
✅ 设置默认分支为main
✅ 创建空的commit历史
```

**方法二：克隆已有仓库**

当队长已经创建了仓库，你需要克隆到本地：

```powershell
# 基本克隆
git clone https://gitee.com/team/project.git

# 指定文件夹名称
git clone https://gitee.com/team/project.git my-project

# 克隆特定分支
git clone -b develop https://gitee.com/team/project.git

# 查看克隆后的信息
cd project
git remote -v

# 输出：
# origin  https://gitee.com/team/project.git (fetch)
# origin  https://gitee.com/team/project.git (push)
```

### 3.3 创建Python演示项目

为了更好地学习Git，我们创建一个简单的Python项目：

**创建项目结构**

```powershell
# 创建目录结构
mkdir -p src tests docs

# 创建Python文件
touch src/__init__.py
touch src/main.py
touch src/data_processor.py
touch tests/__init__.py
touch tests/test_processor.py
```

**Python代码示例：数据处理模块**

这是一个完整的数据处理类，我们用它来演示Git的各种操作：

```python
# src/data_processor.py
"""数据处理器模块 - 用于比赛项目的数据处理

这个模块演示了Python面向对象编程的各种特性，
包括类型提示、文档字符串、异常处理等。
"""

from typing import List, Dict, Any, Optional
import json
from datetime import datetime
import os


class DataProcessor:
    """数据处理器类
    
    用于处理比赛项目中的数据清洗和转换。
    
    Attributes:
        name: 处理器的名称
        data: 存储的原始数据
        processed_count: 已处理的数据条数
    """
    
    def __init__(self, name: str = "default") -> None:
        """初始化数据处理器
        
        Args:
            name: 处理器的名称，用于标识不同的处理器
        """
        self.name = name
        self.data: List[Dict[str, Any]] = []
        self.processed_count: int = 0
        self.created_at: str = datetime.now().isoformat()
    
    def load_data(self, filepath: str) -> bool:
        """加载JSON格式的数据文件
        
        Args:
            filepath: 数据文件的路径
            
        Returns:
            bool: 加载是否成功
        """
        try:
            # 检查文件是否存在
            if not os.path.exists(filepath):
                print(f"文件 {filepath} 未找到")
                return False
            
            # 读取并解析JSON
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()
                self.data = json.loads(content) if content.strip() else []
            
            print(f"成功加载 {len(self.data)} 条数据")
            return True
            
        except json.JSONDecodeError as e:
            print(f"JSON解析错误: {e}")
            return False
        except Exception as e:
            print(f"加载失败: {e}")
            return False
    
    def process(self) -> List[Dict[str, Any]]:
        """处理加载的数据
        
        对每条数据进行转换和增强处理。
        
        Returns:
            List[Dict]: 处理后的数据列表
        """
        results: List[Dict[str, Any]] = []
        
        for item in self.data:
            # 处理单条数据
            processed_item = {
                'timestamp': datetime.now().isoformat(),
                'original': item,
                'processed_value': self._calculate(item),
                'processor_name': self.name
            }
            results.append(processed_item)
            self.processed_count += 1
        
        return results
    
    def _calculate(self, item: Dict) -> float:
        """内部计算方法
        
        根据数据项计算处理值。
        
        Args:
            item: 单条数据
            
        Returns:
            float: 计算结果
        """
        values = item.get('values', [])
        if not values:
            return 0.0
        
        # 计算平均值
        return sum(values) / len(values)
    
    def save_results(self, results: List, output_path: str) -> bool:
        """保存处理结果到文件
        
        Args:
            results: 要保存的结果数据
            output_path: 输出文件路径
            
        Returns:
            bool: 保存是否成功
        """
        try:
            with open(output_path, 'w', encoding='utf-8') as f:
                json.dump(results, f, ensure_ascii=False, indent=2)
            print(f"结果已保存到 {output_path}")
            return True
        except Exception as e:
            print(f"保存失败: {e}")
            return False
    
    def get_statistics(self) -> Dict[str, Any]:
        """获取处理器统计信息
        
        Returns:
            Dict: 包含处理器名称、数据条数、处理条数等统计信息
        """
        return {
            'name': self.name,
            'total_items': len(self.data),
            'processed_items': self.processed_count,
            'created_at': self.created_at
        }


# 模块主程序入口
if __name__ == "__main__":
    # 创建处理器实例
    processor = DataProcessor("比赛数据处理器")
    
    # 打印统计信息
    stats = processor.get_statistics()
    print(f"初始化 {stats['name']}")
    print(f"统计信息: {json.dumps(stats, indent=2, ensure_ascii=False)}")
```

### 3.4 基本命令：add、commit、status

**命令一：git status**

`git status`是查看仓库状态最常用的命令：

```powershell
# 查看当前仓库状态
git status

# 简洁格式（推荐）
git status -s

# 输出示例（详细模式）：
# On branch main
# No commits yet
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#   src/
#   tests/
#   docs/

# 状态符号解释：
# ?? = 未跟踪的文件（Untracked）
# A  = 新添加到暂存区的文件（Added）
# M  = 修改过的文件（Modified）
# D  = 删除的文件（Deleted）
# R  = 重命名的文件（Renamed）
```

**命令二：git add**

`git add`将文件添加到暂存区，为提交做准备：

```powershell
# 添加单个文件
git add src/data_processor.py

# 添加整个目录
git add src/

# 添加所有文件（当前目录下的所有变更）
git add .

# 添加所有修改和删除，但不添加未跟踪的新文件
git add -u

# 添加特定模式的所有文件
git add *.py

# 查看暂存区
git status
# 输出：
# Changes to be committed:
#   new file:   src/data_processor.py
```

**实际演示流程**：

```powershell
# Step 1: 查看状态
git status -s
# ?? src/__init__.py
# ?? src/main.py
# ?? src/data_processor.py
# ?? tests/__init__.py
# ?? docs/

# Step 2: 添加Python文件到暂存区
git add src/

# Step 3: 再次查看状态
git status -s
# A  src/__init__.py
# A  src/main.py
# A  src/data_processor.py
# ?? tests/__init__.py
# ?? docs/
```

**命令三：git commit**

`git commit`将暂存区的内容保存到仓库，形成一个历史快照：

```powershell
# 基本提交（推荐使用）
git commit -m "feat: 添加数据处理模块"

# 提交并显示变更统计
git commit -v

# 提交所有已跟踪文件的修改（不包括新文件）
git commit -am "fix: 修复数据处理逻辑"

# 修改最后一次提交（追加遗漏的文件）
git add tests/
git commit --amend --no-edit

# 查看提交历史
git log

# 简洁格式
git log --oneline
```

**提交信息规范**：

良好的提交信息能让团队成员快速理解你的修改。建议使用以下格式：

```bash
<type>: <subject>

<body>

<footer>
```

**Type类型**：

```
feat: 新功能（Feature）
     示例：feat: 添加用户登录功能

fix: 修复bug
     示例：fix: 修复登录页面样式错乱

docs: 文档变更
     示例：docs: 更新README使用说明

style: 代码格式（不影响功能）
     示例：style: 统一代码缩进为4空格

refactor: 重构（不是新功能或bug修复）
     示例：refactor: 重构数据处理模块

test: 测试相关
     示例：test: 添加单元测试

chore: 构建过程或辅助工具的变动
     示例：chore: 更新依赖包版本
```

**完整提交示例**：

```powershell
git commit -m "feat: 添加数据处理器基础功能

- 实现DataProcessor类
- 支持JSON文件加载
- 实现基本的数据处理逻辑
- 添加错误处理机制
- 包含单元测试

Closes #001
"
```

### 3.5 查看历史记录和差异

**命令：git log**

查看提交历史：

```powershell
# 完整格式
git log

# 简洁格式（一行一个提交）
git log --oneline

# 图形化显示分支和合并
git log --graph --oneline --all

# 显示最近5次提交
git log -5

# 显示文件变更统计
git log --stat

# 显示特定文件的变更
git log -- src/data_processor.py
```

**git log 输出示例**：

```
commit abc123def456
Author: 刘航宇 <3364451258@qq.com>
Date:   2026-04-23 10:30:00

    feat: 添加数据处理模块

    - 实现DataProcessor类
    - 支持JSON文件加载
    - 实现基本的数据处理逻辑

commit def456abc789
Author: 刘航宇 <3364451258@qq.com>
Date:   2026-04-23 09:15:00

    init: 初始化项目结构
```

**命令：git diff**

查看文件变更：

```powershell
# 查看工作区的变更（未暂存）
git diff

# 查看暂存区的变更（已暂存）
git diff --staged

# 查看两个版本的差异
git diff HEAD~1 HEAD

# 查看特定文件的变更
git diff src/data_processor.py

# 查看简略统计
git diff --stat
```

**git diff 输出示例**：

```diff
diff --git a/src/data_processor.py b/src/data_processor.py
index 1234567..89abcdef 100644
--- a/src/data_processor.py
+++ b/src/data_processor.py
@@ -10,6 +10,7 @@ class DataProcessor:
         self.data: List[Dict[str, Any]] = []
         self.processed_count: int = 0
+        self.created_at: str = datetime.now().isoformat()
```

**diff符号说明**：

```
@@ -10,6 +10,7 @@
  ↑   ↑  ↑  ↑
  文件位置 变更的行数

+ 新增的行
- 删除的行
  修改的行
```

### 3.6 .gitignore文件

.gitignore文件告诉Git忽略某些文件，不纳入版本控制：

**为什么需要.gitignore？**

```
应该忽略的文件类型：
- 编译输出（__pycache__/、*.pyc）
- 依赖包（venv/、node_modules/）
- 敏感信息（config.py、.env）
- 大文件（data/、*.zip）
- 系统文件（.DS_Store、Thumbs.db）
- 日志文件（*.log）
```

**Python项目的.gitignore示例**：

```bash
# .gitignore

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# 虚拟环境
venv/
ENV/
env/
.venv/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# 数据文件
*.csv
*.xlsx
*.json
data/
models/*.pth
!config.json  # 例外：保留config.json

# 日志
*.log

# 系统文件
.DS_Store
Thumbs.db
```

**创建.gitignore**：

```powershell
# 方法一：手动创建
touch .gitignore
code .gitignore

# 方法二：从GitHub模板复制
# https://github.com/github/gitignore
# Python.gitignore

# 方法三：使用命令行
echo "__pycache__/" >> .gitignore
echo "*.pyc" >> .gitignore
```

**查看Git会忽略哪些文件**：

```powershell
# 查看被忽略的文件
git status --ignored

# 忽略文件模式
git check-ignore -v <file>
```

### 3.7 本章小结

本章中，我们学习了Git的基本操作：

```
💻 基础配置
   - git config：设置用户名、邮箱、编辑器
   
📁 仓库管理
   - git init：创建新仓库
   - git clone：克隆远程仓库
   
📝 日常操作
   - git status：查看状态
   - git add：添加到暂存区
   - git commit：提交到仓库
   
🔍 查看历史
   - git log：查看提交历史
   - git diff：查看变更内容
   
⚙️ .gitignore
   - 忽略不需要版本控制的文件
   - Python项目常见忽略规则
```

下一章，我们将学习Git最强大的功能之一——分支管理。

---

## 第四章：分支管理——团队协作的核心

### 4.1 为什么需要分支？

在深入学习分支之前，让我们理解为什么分支如此重要。

**没有分支的问题**：

想象一个没有分支的开发场景：

```
时间线：
Day 1: 小明开始开发"用户认证"功能
Day 2: 小红需要修复一个紧急bug
Day 3: 小明的新功能还没完成，不能提交代码
Day 4: 小红的bug修复和小明的新功能混在一起，乱成一团
Day 5: 比赛提交日期，但代码不稳定
```

**使用分支的优势**：

```
解决方案：每个人在自己的分支上工作

时间线（使用分支）：
Day 1: 
  main: 稳定版本
  ├── 小明: feature/user-auth → 开发中
  └── 小红: (继续在main工作)

Day 2: 小红发现bug
  ├── main: 从main创建hotfix分支
  └── 小红: 在hotfix修复bug → 测试 → 合并到main

Day 3:
  main: 已包含小红修复的bug
  ├── 小明: feature/user-auth → 开发中（不受影响）
  └── 小红: 切换到main，继续其他工作

Day 4:
  小明: 完成功能 → 测试 → 合并到main

Day 5:
  main: 稳定的新版本，包含新功能和bug修复
```

**分支的核心价值**：

```
✅ 并行开发：多人同时开发不同功能，互不干扰
✅ 功能隔离：新功能在独立分支开发，不影响主版本
✅ 快速回溯：出问题可以立即切换到稳定版本
✅ 灵活实验：可以在分支上尝试，失败了就删掉
✅ 清晰流程：每个分支有明确的用途和生命周期
```

### 4.2 分支相关命令

**查看分支**

```powershell
# 查看本地分支（当前分支前面有*）
git branch

# 查看所有分支（包括远程）
git branch -a

# 查看分支详细信息
git branch -v

# 查看已合并的分支
git branch --merged

# 查看未合并的分支
git branch --no-merged
```

**创建分支**

```powershell
# 创建新分支（但不切换）
git branch feature/data-processor

# 创建并切换到新分支（推荐）
git checkout -b feature/data-processor

# 新版Git推荐使用switch命令
git switch -c feature/data-processor  # 创建并切换
git switch feature/data-processor      # 仅切换

# 从特定提交创建分支
git checkout -b feature/start-from v1.0.0
```

**切换分支**

```powershell
# 切换到已有分支
git checkout feature/data-processor

# 新版Git
git switch feature/data-processor

# 切换回主分支
git checkout main
git switch main
```

**删除分支**

```powershell
# 删除已合并的分支（安全删除）
git branch -d feature/completed

# 强制删除分支（即使未合并）
git branch -D feature/discard

# 删除远程分支
git push origin --delete feature/old
```

### 4.3 分支操作实战演示

**场景：三人团队开发比赛项目**

团队成员：
- 小明：队长，负责main和develop分支
- 小红：开发"数据处理"功能
- 小刚：开发"界面展示"功能

**Step 1：队长初始化仓库**

```powershell
# 队长：创建仓库
mkdir competition-project
cd competition-project
git init

# 创建主开发分支
git checkout -b develop

# 创建初始文件
echo "# 比赛项目" > README.md
git add README.md
git commit -m "init: 创建项目基础结构"

# 添加远程仓库
git remote add origin https://gitee.com/team/competition-project.git

# 推送分支到远程
git push -u origin main
git push -u origin develop
```

**Step 2：队员克隆仓库**

```powershell
# 小红和小刚：克隆仓库
git clone https://gitee.com/team/competition-project.git
cd competition-project

# 切换到develop分支
git checkout develop

# 拉取最新代码
git pull origin develop
```

**Step 3：队员创建自己的功能分支**

```powershell
# 小红：创建数据处理分支
git checkout -b feature/data-processor

# 小刚：创建界面分支
git checkout -b feature/ui-display
```

**Step 4：各自开发并提交**

```powershell
# 小红：在feature/data-processor分支工作
# ... 编辑 src/data_processor.py ...

git add src/
git commit -m "feat: 添加数据处理模块

- 实现DataProcessor类
- 支持JSON数据加载
- 实现基本的数据处理逻辑"

# 推送到远程
git push origin feature/data-processor

# 小刚：在feature/ui-display分支工作
# ... 编辑 src/ui.py ...

git add src/
git commit -m "feat: 添加界面模块

- 实现基础UI布局
- 添加数据可视化组件"

git push origin feature/ui-display
```

**Step 5：队长查看分支状态**

```powershell
# 查看所有分支
git branch -a

# 输出示例：
#   feature/data-processor    # 小红的分支
#   feature/ui-display       # 小刚的分支
# * develop                  # 当前分支（标记*）
#   main                     # 主分支
#   remotes/origin/develop  # 远程develop
#   remotes/origin/main     # 远程main
```

### 4.4 合并分支

**命令：git merge - 合并分支**

合并是将一个分支的修改应用到另一个分支上。

**Fast-forward合并（快速合并）**

适用场景：目标分支没有新的提交，Git可以直接移动指针。

```powershell
# 假设当前在develop分支
# feature分支有新的提交

# 执行合并
git checkout develop
git merge feature/data-processor

# 输出：
# Updating a1b2c3d..e4f5g6h
# Fast-forward
#  src/data_processor.py | 50 +++++++++++++++++++++++++++
#  1 file changed, 50 insertions(+)
```

合并后，develop分支的指针直接移动到feature分支的最新提交，就像"快进"一样。

**Three-way合并（三方合并）**

适用场景：目标分支也有新的提交，Git需要进行三方合并。

```powershell
# develop分支有新提交（不是fast-forward的情况）
# feature分支有新提交

# 执行合并
git checkout develop
git merge feature/ui-display

# 输出：
# Merge made by the 'recursive' strategy.
#  src/ui.py | 30 ++++++++++++++++++
#  1 file changed, 30 insertions(+)
```

Git创建了一个新的"合并提交"，有两个父提交。

**解决冲突后合并**

如果两个分支修改了同一文件的同一部分，会产生冲突：

```powershell
# 合并时出现冲突
git merge feature/conflict-branch

# 输出：
# CONFLICT (content): Merge conflict in src/utils.py
# Automatic merge failed; fix conflicts and then commit

# 手动解决冲突
# 编辑 src/utils.py，找到冲突标记
<<<<<<< HEAD
    # 当前分支的代码
    result = calculate_v1()
=======
    # 合并进来的分支的代码
    result = calculate_v2()
>>>>>>> feature/conflict-branch

# 删除标记，保留想要的代码
result = calculate_v2()  # 选择其中一个

# 标记冲突已解决
git add src/utils.py

# 提交合并
git commit -m "merge: 合并feature分支，解决冲突"
```

### 4.5 Rebase：变基操作

**概念解释**

Rebase（变基）是将当前分支的修改"移植"到另一个分支的顶部，创建更线性的历史。

```
Before rebase:
main:     A---B---C
              \
feature:       D---E

After rebase (feature rebase到main):
main:     A---B---C
                  \
feature:           D'---E'   ← 重新应用了D和E的修改
```

**命令：git rebase**

```powershell
# 将当前分支变基到main分支
git checkout feature/data-processor
git rebase main

# 输出：
# First, rewinding head to replay your work onto it...
# Applying: feat: 添加数据处理功能

# 如果有冲突，解决后继续
git rebase --continue

# 或者放弃rebase
git rebase --abort
```

**merge vs rebase 对比**

| 特性 | merge | rebase |
|------|-------|--------|
| 历史记录 | 保留完整历史，包括合并点 | 历史更线性，简洁 |
| 是否产生新提交 | 产生merge commit | 不产生额外commit |
| 冲突解决 | 可能需要多次解决 | 每个提交逐一解决 |
| 适用场景 | 公共分支合并 | 本地分支整理 |
| 风险 | 低 | 高（不要rebase已推送的公共分支） |

**何时使用？**

```
✅ merge：合并到main/develop等主分支
✅ rebase：整理本地未推送的提交
✅ rebase：保持分支历史线性

❌ rebase：不要rebase已经推送的公共分支！
   原因：会改变提交历史，可能导致队友的仓库混乱
```

**实际使用建议**：

```powershell
# 推荐流程：
# 1. 在功能分支上rebase到develop（整理历史）
git checkout feature/my-feature
git rebase develop

# 2. 切换到develop
git checkout develop

# 3. 使用merge合并（保持公共分支历史完整）
git merge feature/my-feature
```

### 4.6 分支命名规范

良好的分支命名能让团队协作更清晰：

**推荐命名规范**

```bash
# 功能分支
feature/<功能描述>
feature/data-processor           # 数据处理功能
feature/user-authentication      # 用户认证功能
feature/image-recognition         # 图像识别功能

# 修复分支
bugfix/<问题描述>
bugfix/fix-login-error           # 修复登录错误
bugfix/memory-leak              # 修复内存泄漏

# 发布分支
release/<版本号>
release/v1.0.0                  # 发布v1.0.0版本
release/v2.1.0                  # 发布v2.1.0版本

# 热修复分支
hotfix/<问题描述>
hotfix/critical-security-patch   # 关键安全修复

# 文档分支
docs/<文档内容>
docs/api-reference              # API文档
docs/user-guide                  # 用户指南

# 实验分支
experiment/<实验名称>
experiment/new-algorithm         # 新算法实验
```

**命名原则**：

```
1. 使用小写字母和连字符（-）
   ✅ feature/user-auth
   ❌ Feature/UserAuth
   ❌ feature/user_auth

2. 简洁明了，看名称就知道是什么
   ✅ feature/user-login
   ❌ feature/f1

3. 可以包含关联的issue编号
   feature/user-login-#001

4. 避免过长的名称
   ✅ feature/user-login
   ❌ feature/add-user-login-functionality-and-fix-issues
```

### 4.7 本章小结

本章中，我们深入学习了Git的分支管理：

```
🌿 分支基础
   - 分支的创建、切换、删除
   - 新版Git推荐使用switch命令
   
🔀 分支合并
   - Fast-forward：快速合并
   - Three-way：三方合并
   - 冲突处理流程
   
📍 Rebase变基
   - 变基的原理和应用场景
   - merge vs rebase的选择
   
📏 命名规范
   - feature/bugfix/release/hotfix
   - 简洁、清晰、一致的命名
```

下一章，我们将学习团队协作的核心流程，包括Pull Request和代码审查。

---

## 第五章：团队协作流程——从开发到发布

### 5.1 Git Flow工作流介绍

Git Flow是一套成熟的分支管理模型，由Vincent Driessen提出，特别适合需要管理多个版本的中大型项目。

**分支类型**：

```
长期分支（始终存在）：
├── main/master     # 生产环境代码，始终保持稳定
└── develop         # 开发主分支，集成所有功能开发

短期分支（按需创建）：
├── feature/*       # 功能分支
├── release/*      # 发布分支
└── hotfix/*       # 热修复分支
```

**开发流程图**：

```
develop ←───────────────────────────────────────────┐
  │                                                  │
  ├── feature/A ───────────────────────────┐          │
  │                                      ↓          │
  │                                   合并           │
  │                                                  │
  ├── feature/B ──────────────────┐       │          │
  │                             ↓       │          │
  │                          合并        │          │
  │                             │       │          │
  ├── feature/C ─────────────┐  │       │          │
  │                        ↓  │  │       │          │
  │                     合并   │  │       │          │
  │                        │   │  │       │          │
  └────────────────────────┼───┴──┴───────┘          │
                           ↓                          │
                      测试完成                        │
                           ↓                          │
                     release/v1.0                    │
                           ↓                          │
                       发布上线                        │
                           ↓                          │
                        main                         │
```

**各分支用途**：

```
main分支：
- 只包含正式发布版本的代码
- 永远保持稳定可发布状态
- 只能从release或hotfix合并

develop分支：
- 集成所有开发中的功能
- 下一版本的代码库
- 只能从feature、release、hotfix合并

feature分支：
- 从develop创建
- 开发特定功能
- 完成后退回develop

release分支：
- 从develop创建
- 准备发布版本
- 修复发布前的bug
- 完成后合并到main和develop

hotfix分支：
- 从main创建
- 紧急修复生产环境问题
- 完成后合并到main和develop
```

### 5.2 Pull Request / Merge Request

**概念解释**

Pull Request（PR）和Merge Request（MR）是现代团队协作的核心。它们是申请将自己的分支合并到目标分支的请求，同时也是代码审查的载体。

```
Pull Request 工作流程：

1. 从develop创建功能分支
   git checkout -b feature/new-feature develop

2. 在功能分支上开发并提交
   git commit -m "feat: 添加新功能"

3. 推送到远程仓库
   git push origin feature/new-feature

4. 在GitHub/Gitee上创建Pull Request
   - 选择源分支：feature/new-feature
   - 选择目标分支：develop

5. 队友/队长审查代码
   - 查看代码改动
   - 提出评论和建议

6. 讨论并修改（如有需要）
   - 提交修复
   - PR自动更新

7. 合并到目标分支
   - 代码审查通过后
   - 点击Merge按钮
   - PR完成
```

**GitHub/Gitee创建PR示例**

在创建Pull Request时，填写清晰的描述：

```markdown
# Pull Request 标题
feat: 添加数据处理模块

# Pull Request 内容

## 功能描述
实现了DataProcessor类，支持JSON数据的加载和处理。
这个模块将用于比赛项目的数据清洗和分析。

## 改动内容
- 新增DataProcessor类
- 实现load_data()方法
- 实现process()方法
- 实现save_results()方法
- 添加错误处理机制

## 测试情况
- [x] 单元测试通过
- [x] 手动测试通过
- [x] 代码覆盖率达到80%

## 截图（如有）

## 相关Issue
Closes #001

## 其他说明
- 遵循PEP8代码规范
- 包含完整的类型注解
- 已更新README文档
```

### 5.3 代码审查基础

**为什么需要代码审查？**

代码审查是团队协作中保证代码质量的关键环节：

```
代码审查的好处：

✅ 发现bug和潜在问题
   - 审查者以"新鲜眼光"看待代码
   - 能发现作者忽略的问题
   
✅ 保证代码质量
   - 统一代码风格
   - 遵循最佳实践
   - 避免技术债务
   
✅ 知识共享和团队学习
   - 团队成员了解彼此的代码
   - 传播好的实践和技术
   - 减少"单点故障"风险
   
✅ 统一代码风格
   - 保持代码一致性
   - 便于维护和阅读
```

**代码审查检查清单**

审查代码时，可以参考以下清单：

```markdown
## 代码审查清单

### 功能正确性
- [ ] 代码逻辑是否正确？
- [ ] 是否处理了边界情况？
- [ ] 是否有单元测试？
- [ ] 测试覆盖是否足够？

### 代码质量
- [ ] 命名是否清晰、有意义？
- [ ] 是否有重复代码（DRY原则）？
- [ ] 是否遵循项目的代码规范？
- [ ] 注释是否清晰、必要？

### 性能
- [ ] 是否有性能问题？
- [ ] 是否有内存泄漏？
- [ ] 算法复杂度是否合理？
- [ ] 是否做了不必要的重复计算？

### 安全性
- [ ] 是否有安全漏洞？
- [ ] 是否正确处理用户输入？
- [ ] 是否泄露敏感信息？
- [ ] 是否有SQL注入、XSS等风险？

### 可维护性
- [ ] 代码是否易于理解？
- [ ] 是否符合单一职责原则？
- [ ] 是否有适当的抽象？
- [ ] 文档是否更新？
```

**审查示例：发现的问题**

审查前（有问题）：

```python
def process_user_data(data):
    # 处理用户数据
    result = data['name'] + data['age']  # 类型错误：字符串不能直接拼接数字
    file = open('output.txt', 'w')       # 资源泄漏：文件可能不会关闭
    file.write(result)
    return result

# 问题分析：
# 1. data['age']是数字，与字符串拼接会报错
# 2. 文件打开后没有关闭，可能导致资源泄漏
# 3. 缺少错误处理
```

审查后（修复后）：

```python
def process_user_data(data: dict) -> str:
    """处理用户数据
    
    Args:
        data: 包含name和age的字典
        
    Returns:
        格式化后的用户信息字符串
        
    Raises:
        KeyError: 当data缺少必要字段时
        ValueError: 当数据格式错误时
    """
    try:
        # 获取数据，带默认值防止KeyError
        name = data.get('name', '')
        age = data.get('age', 0)
        
        # 类型检查和转换
        if not isinstance(age, (int, float)):
            raise ValueError(f"age必须是数字，当前类型: {type(age)}")
        
        # 正确处理类型转换
        result = f"{name} - Age: {age}"
        
        # 使用with语句确保文件正确关闭
        output_path = 'output.txt'
        with open(output_path, 'w', encoding='utf-8') as file:
            file.write(result)
        
        return result
        
    except KeyError as e:
        print(f"缺少必要字段: {e}")
        raise
```

### 5.4 团队协作实战：完整的开发流程

**场景：三人团队开发"智能数据分析系统"**

**团队分工**：

| 角色 | 姓名 | 职责 | 分支 |
|------|------|------|------|
| 队长 | 小明 | 项目负责人、develop分支、代码审查 | develop |
| 队员A | 小红 | 数据采集模块开发 | feature/data-collection |
| 队员B | 小刚 | 数据可视化模块开发 | feature/data-visualization |

**Day 1：项目初始化**

队长初始化项目仓库：

```powershell
# 小明：初始化项目
mkdir smart-data-analysis
cd smart-data-analysis
git init

# 创建develop分支
git checkout -b develop

# 创建项目基础结构
mkdir -p src/{data_collection,data_analysis,visualization}
mkdir -p tests docs

# 创建基础文件
echo "# 智能数据分析系统" > README.md
echo "比赛：中国大学生计算机设计大赛" >> README.md
echo "团队：XXX大学" >> README.md

# 创建.gitignore
echo "python\n__pycache__/" > .gitignore
echo "venv/" >> .gitignore
echo "data/" >> .gitignore

# 初始提交
git add .
git commit -m "init: 创建项目基础结构

- 创建项目目录结构
- 添加.gitignore
- 添加基础README"

# 添加远程仓库
git remote add origin https://gitee.com/team/smart-data-analysis.git

# 推送分支到远程
git push -u origin develop

# 小明分享仓库给队友
# （通过Gitee/GitHub的团队设置添加成员）
```

**Day 2-3：小红开发数据采集模块**

小红克隆仓库并创建功能分支：

```powershell
# 小红：克隆仓库
git clone https://gitee.com/team/smart-data-analysis.git
cd smart-data-analysis

# 切换到develop分支
git checkout develop

# 拉取最新代码
git pull origin develop

# 创建功能分支
git checkout -b feature/data-collection

# 创建数据采集模块
cat > src/data_collection/collector.py << 'EOF'
"""数据采集器模块

用于从各种API和数据源采集数据。
支持重试机制和错误处理。
"""

import requests
from typing import List, Dict, Optional
import time
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class DataCollector:
    """数据采集器类
    
    用于从RESTful API采集数据。
    支持超时设置和自动重试。
    
    Attributes:
        base_url: API的基础URL
        session: HTTP会话
        timeout: 请求超时时间（秒）
        retry_count: 最大重试次数
    """
    
    def __init__(self, base_url: str, timeout: int = 30):
        """初始化数据采集器
        
        Args:
            base_url: API的基础URL
            timeout: 请求超时时间（秒）
        """
        self.base_url = base_url.rstrip('/')
        self.timeout = timeout
        self.retry_count = 3
        
        # 创建会话，支持连接复用
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'SmartDataAnalysis/1.0',
            'Accept': 'application/json'
        })
    
    def fetch_data(self, endpoint: str, params: Optional[Dict] = None) -> List[Dict]:
        """从API获取数据
        
        Args:
            endpoint: API端点路径
            params: 查询参数
            
        Returns:
            API返回的数据列表
            
        Raises:
            requests.RequestException: 请求失败时抛出
        """
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        
        logger.info(f"Fetching data from: {url}")
        
        response = self.session.get(
            url, 
            params=params, 
            timeout=self.timeout
        )
        response.raise_for_status()
        
        data = response.json()
        logger.info(f"Fetched {len(data)} items")
        
        return data
    
    def collect_with_retry(self, endpoint: str, params: Optional[Dict] = None) -> List[Dict]:
        """带重试机制的数据采集
        
        使用指数退避策略进行重试。
        
        Args:
            endpoint: API端点路径
            params: 查询参数
            
        Returns:
            API返回的数据列表
            
        Raises:
            requests.RequestException: 所有重试都失败时抛出
        """
        last_error = None
        
        for attempt in range(self.retry_count):
            try:
                return self.fetch_data(endpoint, params)
            except requests.RequestException as e:
                last_error = e
                if attempt < self.retry_count - 1:
                    # 指数退避：2^attempt 秒
                    wait_time = 2 ** attempt
                    logger.warning(f"Attempt {attempt + 1} failed: {e}")
                    logger.info(f"Retrying in {wait_time} seconds...")
                    time.sleep(wait_time)
                else:
                    logger.error(f"All {self.retry_count} attempts failed")
        
        raise last_error


# 使用示例
if __name__ == "__main__":
    collector = DataCollector("https://api.example.com")
    
    try:
        data = collector.collect_with_retry("/data", {"page": 1})
        print(f"Successfully collected {len(data)} items")
    except requests.RequestException as e:
        print(f"Failed to collect data: {e}")
EOF

# 提交代码
git add src/data_collection/
git commit -m "feat: 添加DataCollector类

- 实现基础的fetch_data方法
- 添加请求超时和错误处理
- 实现带重试机制的采集方法
- 使用requests.Session优化连接

Closes #001"

# 推送到远程
git push origin feature/data-collection

# 创建Pull Request（在网页端操作）
# 选择 feature/data-collection → develop
```

**Day 2-3：小刚开发数据可视化模块**

```powershell
# 小刚：克隆仓库
git clone https://gitee.com/team/smart-data-analysis.git
cd smart-data-analysis

# 创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/data-visualization

# 创建可视化模块
cat > src/visualization/chart_generator.py << 'EOF'
"""图表生成器模块

使用Matplotlib生成各种类型的图表。
支持折线图、柱状图、饼图等。
"""

import matplotlib.pyplot as plt
from typing import List, Optional, Dict
import matplotlib
import numpy as np

# 设置非交互式后端（适合服务器环境）
matplotlib.use('Agg')


class ChartGenerator:
    """图表生成器类
    
    用于生成数据可视化图表。
    支持多种图表类型和自定义样式。
    
    Attributes:
        style: 图表样式
        figure_size: 图表大小
        dpi: 图片分辨率
    """
    
    def __init__(self, style: str = 'seaborn', figure_size: tuple = (10, 6)):
        """初始化图表生成器
        
        Args:
            style: Matplotlib样式名称
            figure_size: 图表大小（宽，高）
        """
        try:
            plt.style.use(style)
        except:
            plt.style.use('default')
        
        self.figure_size = figure_size
        self.dpi = 300
    
    def plot_line_chart(
        self, 
        data: List[float], 
        labels: List[str],
        title: str, 
        xlabel: str = "X轴",
        ylabel: str = "Y轴",
        output_path: str = "line_chart.png"
    ) -> bool:
        """绘制折线图
        
        Args:
            data: 数据列表
            labels: X轴标签
            title: 图表标题
            xlabel: X轴标签
            ylabel: Y轴标签
            output_path: 输出文件路径
            
        Returns:
            是否成功保存
        """
        try:
            plt.figure(figsize=self.figure_size)
            plt.plot(labels, data, marker='o', linewidth=2, markersize=8)
            
            plt.title(title, fontsize=14, fontweight='bold')
            plt.xlabel(xlabel, fontsize=12)
            plt.ylabel(ylabel, fontsize=12)
            plt.grid(True, alpha=0.3, linestyle='--')
            
            plt.xticks(rotation=45, ha='right')
            plt.tight_layout()
            
            plt.savefig(output_path, dpi=self.dpi, bbox_inches='tight')
            plt.close()
            
            return True
            
        except Exception as e:
            print(f"绘图失败: {e}")
            plt.close()
            return False
    
    def plot_bar_chart(
        self, 
        categories: List[str], 
        values: List[float],
        title: str, 
        xlabel: str = "类别",
        ylabel: str = "数值",
        output_path: str = "bar_chart.png"
    ) -> bool:
        """绘制柱状图
        
        Args:
            categories: 类别列表
            values: 数值列表
            title: 图表标题
            xlabel: X轴标签
            ylabel: Y轴标签
            output_path: 输出文件路径
            
        Returns:
            是否成功保存
        """
        try:
            plt.figure(figsize=self.figure_size)
            
            x_pos = np.arange(len(categories))
            plt.bar(x_pos, values, color='skyblue', edgecolor='navy', alpha=0.8)
            
            plt.title(title, fontsize=14, fontweight='bold')
            plt.xlabel(xlabel, fontsize=12)
            plt.ylabel(ylabel, fontsize=12)
            plt.xticks(x_pos, categories, rotation=45, ha='right')
            
            plt.tight_layout()
            plt.savefig(output_path, dpi=self.dpi, bbox_inches='tight')
            plt.close()
            
            return True
            
        except Exception as e:
            print(f"绘图失败: {e}")
            plt.close()
            return False


# 使用示例
if __name__ == "__main__":
    generator = ChartGenerator()
    
    # 测试折线图
    data = [10, 25, 30, 45, 50]
    labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May']
    generator.plot_line_chart(
        data, labels,
        title="Monthly Sales",
        output_path="sales_line.png"
    )
    
    # 测试柱状图
    categories = ['A', 'B', 'C', 'D']
    values = [23, 45, 56, 78]
    generator.plot_bar_chart(
        categories, values,
        title="Category Comparison",
        output_path="category_bar.png"
    )
EOF

# 提交代码
git add src/visualization/
git commit -m "feat: 添加ChartGenerator类

- 实现折线图绘制功能
- 实现柱状图绘制功能
- 添加自定义样式和标签
- 添加错误处理机制

Closes #002"

git push origin feature/data-visualization

# 创建Pull Request
```

**Day 5：代码审查与合并**

队长小明审查并合并代码：

```powershell
# 小明：拉取最新的分支信息
git fetch origin

# 查看Pull Request的改动
git log origin/feature/data-collection --stat

# 在本地测试队友的代码
git checkout -b review/data-collection origin/feature/data-collection
# 运行测试
pytest tests/test_collector.py -v

# 如果代码有问题，在PR下评论指出
# 如果代码没问题，合并代码

# 合并小红的分支
git checkout develop
git merge origin/feature/data-collection
git push origin develop

# 合并小刚的分支
git merge origin/feature/data-visualization
git push origin develop

# 删除已合并的功能分支
git branch -d feature/data-collection
git branch -d feature/data-visualization
git push origin --delete feature/data-collection
git push origin --delete feature/data-visualization

# 小红和小刚：更新本地仓库
git checkout develop
git pull origin develop
```

### 5.5 版本标签管理

**命令：git tag - 标记重要版本**

标签用于标记重要的提交点，通常用于版本发布。

```powershell
# 创建轻量标签
git tag v1.0.0

# 创建附注标签（推荐，包含更多信息）
git tag -a v1.0.0 -m "版本1.0.0：完成基础功能开发"

# 查看所有标签
git tag

# 查看标签详情
git show v1.0.0

# 给历史提交打标签
git tag -a v0.9.0 <commit-hash> -m "版本0.9.0：初始发布"

# 推送标签到远程
git push origin v1.0.0

# 推送所有标签
git push origin --tags

# 删除标签
git tag -d v0.9.0              # 本地
git push origin --delete v0.9.0 # 远程
```

**语义化版本规范**：

```
主版本.次版本.修订号
v1.2.3

含义：
- 1（主版本号）：不兼容的重大更新
- 2（次版本号）：新增功能，向后兼容
- 3（修订号）：bug修复，向后兼容
```

**比赛项目标签示例**：

```powershell
# 初赛提交版本
git tag -a v0.1.0-dev -m "初赛提交版本"
git push origin v0.1.0-dev

# 省赛晋级版本
git tag -a v1.0.0-provincial -m "省赛提交版本"
git push origin v1.0.0-provincial

# 国赛最终版本
git tag -a v2.0.0-final -m "国赛最终提交版本"
git push origin v2.0.0-final
```

### 5.6 本章小结

本章中，我们学习了团队协作的完整流程：

```
🤝 Git Flow工作流
   - 长期分支：main、develop
   - 短期分支：feature、release、hotfix
   - 清晰的分支生命周期

📝 Pull Request流程
   - 创建功能分支
   - 开发并提交
   - 创建Pull Request
   - 代码审查
   - 合并到主分支

✅ 代码审查
   - 审查的重要性和价值
   - 审查检查清单
   - 发现和修复问题

📌 标签管理
   - 创建和管理版本标签
   - 语义化版本规范
   - 比赛项目的标签策略
```

下一章，我们将学习Git中最具挑战性的部分——冲突处理。

---

## 第六章：冲突处理——化干戈为玉帛

### 6.1 什么是冲突？

冲突是Git中最需要手动处理的情况。理解冲突的产生原因，是解决冲突的第一步。

**冲突产生的原理**：

```
场景：小明和小红同时修改了同一文件的同一行

小明的工作（在自己的分支）：
  文件第50行：result = a + b + c  ← 添加了变量c

小红的工作（在自己的分支）：
  文件第50行：result = a * b      ← 改成了乘法

Git无法自动决定：应该保留谁的修改？
→ 产生冲突，需要手动解决
```

**什么时候会产生冲突？**

```
✅ 多人同时修改了同一文件的同一行
✅ 一个人删除文件，另一个人修改了它
✅ 多人修改了同一个分支的名字
```

**什么时候不会冲突？**

```
✅ 修改了不同文件
✅ 修改了同一文件的不同部分
✅ 修改了同一文件但不同行
```

**理解冲突的本质**：

冲突不是"错误"，而是Git的"安全机制"。它告诉你"这里有两个人同时修改了，Git无法自动决定，你来决定保留哪个"。

### 6.2 识别冲突标记

当Git检测到冲突时，它会在文件中添加特殊的标记：

**冲突标记格式**：

```python
<<<<<<< HEAD
    # 当前分支的代码
    result = a + b + c
=======
    # 合并进来的分支的代码
    result = a * b
>>>>>>> feature-branch
```

**解释**：

```
<<<<<<< HEAD
    这部分是被合并的目标分支（HEAD指向的分支）的代码
=======
    这部分是试图合并进来的分支的代码
>>>>>>> feature-branch
    这是那个分支的名称
```

**完整的冲突示例**：

```python
# src/data_processor.py

def calculate(data):
    """数据处理函数"""
    # ... 其他代码省略 ...

<<<<<<< HEAD
    # 队长的修改：添加日志功能
    print(f"开始计算，数据长度: {len(data)}")
    result = sum(data)
=======
    # 小红的修改：添加错误处理
    if not data:
        return 0
    result = sum(data)
>>>>>>> feature/data-processor

    # ... 其他代码省略 ...

<<<<<<< HEAD
    print(f"计算完成，结果: {result}")
=======
    return result
>>>>>>> feature/data-processor
```

**查看冲突文件**：

```powershell
# 查看有冲突的文件
git status

# 输出：
# both modified:   src/data_processor.py

# 查看冲突列表
git diff --name-only --diff-filter=U

# 或者
git status --porcelain | grep -E "^(UU|AU|DU|AA|DD)"

# 在编辑器中查看冲突
code src/data_processor.py
```

### 6.3 解决冲突的方法

**方法一：手动编辑解决（最常用）**

这是最通用、最可靠的方法：

```powershell
# Step 1: 拉取最新代码，产生冲突
git pull origin develop

# 输出：
# Auto-merging src/data_processor.py
# CONFLICT (content): Merge conflict in src/data_processor.py
# Automatic merge failed; fix conflicts and then commit the results.

# Step 2: 打开冲突文件
code src/data_processor.py

# Step 3: 手动编辑，删除冲突标记
# 保留想要的代码（可以是其中一个，也可以是合并两者）

# 解决后的代码示例（保留两者）：
def calculate(data):
    """数据处理函数"""
    # ... 其他代码省略 ...
    
    # 队长的日志
    print(f"开始计算，数据长度: {len(data)}")
    
    # 小红的错误处理
    if not data:
        return 0
    result = sum(data)
    
    # ... 其他代码省略 ...
    
    # 队长的日志
    print(f"计算完成，结果: {result}")
    return result

# Step 4: 添加并提交
git add src/data_processor.py

# Step 5: 提交（不要用-m，用编辑器写清楚）
git commit
# 提交信息：
# merge: 解决与feature/data-processor的冲突
# 
# 保留队长的日志功能和小红的错误处理
# 
# Resolved conflicts in src/data_processor.py
```

**方法二：使用合并工具（更直观）**

```powershell
# 配置合并工具
# VS Code内置Git冲突解决工具

# 或者使用第三方工具
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd "code --wait $MERGED"

# 启动合并工具
git mergetool

# 使用图形界面解决冲突
```

**方法三：接受某一方的版本（快速但不推荐）**

```powershell
# 接受当前分支（HEAD）的版本
git checkout --ours src/data_processor.py
git add src/data_processor.py
git commit -m "merge: 采用当前分支版本解决冲突"

# 或者接受合并进来的分支的版本
git checkout --theirs src/data_processor.py
git add src/data_processor.py
git commit -m "merge: 采用对方分支版本解决冲突"
```

**方法四：放弃合并**

```powershell
# 放弃这次合并
git merge --abort

# 仓库状态回到合并之前
```

### 6.4 避免冲突的最佳实践

预防冲突比解决冲突更重要：

**策略一：频繁拉取和推送**

```powershell
# 每天早上开始工作前
git checkout develop
git pull origin develop

# 完成工作后尽快推送
git add .
git commit -m "feat: 完成功能开发"
git push origin feature/my-feature
```

**策略二：功能分支要小而专注**

```bash
# ❌ 不推荐：一个分支做太多事情
git checkout -b feature/big-feature

# ✅ 推荐：一个分支只做一件事
git checkout -b feature/add-login
git checkout -b feature/add-search
git checkout -b feature/add-export
```

**策略三：及时与队友沟通**

```markdown
# 团队沟通示例

小明：@小红 我要修改 data_processor.py 的第50-60行，大概10分钟
小红：好的，我这边暂时不动那个文件

# 10分钟后

小明：完成了，你可以动那个文件了
小红：好的谢谢
```

**策略四：制定代码规范**

```python
# 约定好代码风格，减少格式冲突
# .editorconfig

root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
```

**策略五：合理安排工作顺序**

```
时序安排建议：

**策略六：善用git pull --rebase**

```powershell
# 保持分支线性的同时获取最新代码
git pull --rebase origin develop

# 注意：如果有冲突，逐个解决
```

### 6.5 冲突解决后的检查清单

每次解决完冲突后，务必检查：

```markdown
## 冲突解决后检查清单

- [ ] 删除了所有冲突标记（<<<<<<<, =======, >>>>>>>）
- [ ] 代码逻辑正确，没有错误
- [ ] 两个人的改动都被正确保留（如果需要）
- [ ] 本地测试通过
- [ ] 提交信息说明了解决方式和原因
- [ ] 通知了相关队友冲突已解决
```

**测试验证**：

```powershell
# 解决冲突后，运行测试确保没有引入新问题
pytest tests/ -v

# 或者运行项目，确保能正常启动
python src/main.py
```

### 6.6 本章小结

本章中，我们学习了Git冲突的处理：

```
⚠️ 冲突认知
   - 冲突是Git的安全机制，不是错误
   - 多人同时修改同一位置时产生
   
🔍 识别冲突
   - 冲突标记：<<<<<<< HEAD, =======, >>>>>>>
   - git status查看冲突文件
   
🛠️ 解决冲突
   - 手动编辑（最推荐）
   - 使用合并工具
   - 接受某一方的版本
   
✅ 避免冲突
   - 频繁push/pull
   - 保持分支小而专注
   - 团队沟通
```

下一章，我们将通过一个完整的比赛场景，展示Git在实战中的应用。

---

## 第七章：比赛场景实战——三人团队的协作范例

### 7.1 比赛项目特点分析

**比赛项目的特殊需求**：

比赛项目与日常开发相比，有其独特的特点：

```
📅 时间紧迫
   - 通常只有几周的准备时间
   - 需要快速迭代，快速产出
   - 后期压力大，容易出错

👥 团队临时
   - 队员可能来自不同专业
   - 编程水平参差不齐
   - 缺乏长期磨合

🔄 迭代快速
   - 初赛 → 复赛 → 决赛
   - 每个阶段都需要有可用版本
   - 可能在短时间内大幅修改

📄 文档重要
   - 技术文档需要详细
   - 演示视频、答辩PPT
   - 说明书、使用指南

🏆 成果展示
   - 需要打包、部署
   - 演示效果很重要
   - 评委需要能实际运行
```

**Git在比赛中的价值**：

```
✅ 多人并行开发，互不干扰
✅ 版本管理，清楚记录每个阶段
✅ 代码审查，保证代码质量
✅ 快速回退，出问题能及时恢复
✅ 文档统一管理，不分散
✅ 备份保障，代码不会丢失
```

### 7.2 三人团队协作范例

**项目背景**：
- 项目名称：智能垃圾分类系统
- 参赛比赛：中国大学生计算机设计大赛
- 准备周期：4周（初赛→复赛）
- 团队成员：小明（队长）、小红、小刚

**团队分工**：

| 角色 | 姓名 | 职责 | 分支 |
|------|------|------|------|
| 队长 | 小明 | 项目架构、算法、代码审查 | develop |
| 队员A | 小红 | 前端界面开发 | feature/frontend |
| 队员B | 小刚 | 后端API、数据库 | feature/backend |

**Week 1：项目初始化**

队长小明创建项目仓库：

```powershell
# 小明：创建项目
mkdir smart-waste-classification
cd smart-waste-classification
git init
git checkout -b develop

# 创建项目结构
mkdir -p src/{models,utils,api}
mkdir -p frontend
mkdir -p docs
mkdir -p tests

# 创建.gitignore
echo "python\n__pycache__/" > .gitignore
echo "venv/" >> .gitignore
echo "*.pth" >> .gitignore
echo "data/" >> .gitignore
echo "models/*.pth" >> .gitignore

# 创建README
echo "# 智能垃圾分类系统" > README.md
echo "比赛：中国大学生计算机设计大赛" >> README.md
echo "团队：XXX大学" >> README.md

# 初始提交
git add .
git commit -m "init: 创建项目基础结构

- 创建目录结构
- 添加.gitignore
- 添加基础README"

# 推送到远程
git remote add origin https://gitee.com/team/smart-waste-classification.git
git push -u origin develop
```

**Week 1-2：队员并行开发**

小红和小刚各自克隆仓库并创建功能分支：

```powershell
# 小红：克隆并创建前端分支
git clone https://gitee.com/team/smart-waste-classification.git
cd smart-waste-classification
git checkout develop
git checkout -b feature/frontend

# ... 开发前端界面 ...
# 创建 frontend/index.html, frontend/style.css, frontend/app.js

git add frontend/
git commit -m "feat: 完成前端界面基础布局

- 添加HTML结构
- 添加基础CSS样式
- 实现图片上传功能

Closes #001"

git push origin feature/frontend

# 小刚：创建后端分支
git checkout develop
git checkout -b feature/backend

# ... 开发后端API ...
cat > src/api/classifier.py << 'EOF'
"""图像分类API模块

使用FastAPI构建的垃圾分类接口服务。
"""

from fastapi import FastAPI, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
import torch
from torchvision import transforms
from PIL import Image
import io
from typing import Dict

app = FastAPI(
    title="垃圾分类API",
    description="智能垃圾分类系统的后端接口"
)

# CORS配置，允许前端跨域访问
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 生产环境应限制为具体域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


class WasteClassifier:
    """垃圾分类器类"""
    
    def __init__(self):
        self.model = None
        self.categories = ['其他垃圾', '厨余垃圾', '可回收垃圾', '有害垃圾']
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
    def load_model(self, model_path: str) -> bool:
        """加载训练好的模型
        
        Args:
            model_path: 模型文件路径
            
        Returns:
            加载是否成功
        """
        try:
            self.model = torch.load(model_path, map_location=self.device)
            self.model.eval()
            return True
        except FileNotFoundError:
            print(f"模型文件未找到: {model_path}")
            return False
    
    async def predict(self, image_data: bytes) -> Dict:
        """预测图片类别
        
        Args:
            image_data: 图片的字节数据
            
        Returns:
            包含预测结果的字典
        """
        # 图片预处理
        image = Image.open(io.BytesIO(image_data))
        
        transform = transforms.Compose([
            transforms.Resize((224, 224)),
            transforms.ToTensor(),
            transforms.Normalize(
                mean=[0.485, 0.456, 0.406],
                std=[0.229, 0.224, 0.225]
            )
        ])
        
        img_tensor = transform(image).unsqueeze(0).to(self.device)
        
        # 预测
        with torch.no_grad():
            outputs = self.model(img_tensor)
            probabilities = torch.softmax(outputs, dim=1)[0]
            _, predicted = torch.max(outputs, 1)
            
            category = self.categories[predicted.item()]
            confidence = probabilities[predicted.item()].item()
        
        return {
            "category": category,
            "confidence": f"{confidence:.2%}",
            "probabilities": {
                cat: f"{prob:.2%}" 
                for cat, prob in zip(self.categories, probabilities.tolist())
            }
        }


# 创建全局分类器实例
classifier = WasteClassifier()


@app.post("/predict")
async def predict_waste(file: UploadFile = File(...)) -> Dict:
    """垃圾分类预测接口
    
    Args:
        file: 上传的图片文件
        
    Returns:
        预测结果，包含分类和置信度
    """
    contents = await file.read()
    result = await classifier.predict(contents)
    return result


@app.get("/health")
async def health_check() -> Dict:
    """健康检查接口"""
    return {
        "status": "healthy",
        "model_loaded": classifier.model is not None,
        "categories": classifier.categories
    }


@app.get("/")
async def root() -> Dict:
    """根路径"""
    return {
        "message": "智能垃圾分类系统 API",
        "version": "1.0.0",
        "docs": "/docs"
    }


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
EOF

git add src/api/
git commit -m "feat: 添加FastAPI垃圾分类接口

- 实现/predict端点，支持图片上传
- 添加/health健康检查端点
- 添加CORS支持
- 实现WasteClassifier类

Closes #002"

git push origin feature/backend
```

**Week 2：代码审查与合并**

队长小明审查并合并代码：

```powershell
# 小明：拉取最新代码
git fetch origin

# 查看并审查小红的分支
git checkout -b review/frontend origin/feature/frontend
# ... 测试代码 ...

# 合并小红的代码
git checkout develop
git merge origin/feature/frontend
git push origin develop

# 审查并合并小刚的代码
git checkout develop
git merge origin/feature/backend
git push origin develop

# 删除功能分支
git branch -d feature/frontend
git branch -d feature/backend
git push origin --delete feature/frontend
git push origin --delete feature/backend

# 推送删除请求给队友
```

**Week 3：省赛提交版本**

```powershell
# 小明：创建省赛提交标签
git checkout develop

# 确保所有代码已合并
git status

# 创建省赛提交版本
git tag -a v1.0.0-provincial -m "省赛提交版本 v1.0.0

功能：
- 基于ResNet的图像分类模型
- RESTful API接口
- 简单的前端界面

技术栈：
- PyTorch深度学习框架
- FastAPI后端框架
- HTML/CSS/JavaScript前端

团队：小明、小红、小刚"

# 推送标签
git push origin v1.0.0-provincial

# 导出代码用于提交
git archive -o submission-provincial.zip --prefix=project/ HEAD
```

**Week 4：决赛优化与最终提交**

如果队伍晋级，继续开发决赛版本：

```powershell
# 创建决赛分支
git checkout develop
git checkout -b release/final

# 创建优化分支
git checkout -b feature/improve-accuracy
# ... 优化模型精度 ...
git commit -m "perf: 提升模型精度至92%"
git push origin feature/improve-accuracy

git checkout -b feature/add-export
# ... 添加数据导出功能 ...
git commit -m "feat: 添加数据导出功能"
git push origin feature/add-export

# 合并所有优化
git checkout develop
git merge feature/improve-accuracy
git merge feature/add-export
git push origin develop

# 创建决赛提交标签
git tag -a v2.0.0-final -m "决赛最终版本 v2.0.0

新增功能：
- 模型精度提升至92%
- 数据导出功能
- 用户反馈系统

性能优化：
- API响应时间减少50%
- 前端加载速度提升"

git push origin v2.0.0-final
```

### 7.3 文档管理

比赛项目通常需要提交大量文档，使用Git管理文档是个好选择：

**创建文档分支**：

```powershell
# 创建文档分支
git checkout develop
git checkout -b docs

# 创建文档目录
mkdir -p docs/{技术文档,使用手册,答辩PPT}
```

**技术文档示例**：

```markdown
# 智能垃圾分类系统 - 系统设计文档

## 1. 系统架构

### 1.1 整体架构
系统采用前后端分离架构...

### 1.2 技术选型

| 层级 | 技术 | 说明 |
|------|------|------|
| 前端 | HTML5 + CSS3 + JavaScript | 轻量级界面 |
| 后端 | FastAPI | 高性能Python框架 |
| 模型 | PyTorch + ResNet | 深度学习图像分类 |
| 部署 | Docker | 容器化部署 |

### 1.3 API接口设计

```
POST /predict
- 功能：图片分类预测
- 输入：图片文件
- 输出：分类结果和置信度

GET /health
- 功能：健康检查
- 输出：服务状态
```

## 2. 数据流程

```
用户上传图片
    ↓
前端界面
    ↓
API接口 /predict
    ↓
图像预处理
    ↓
模型推理
    ↓
返回结果
```

# 文档提交
git add docs/
git commit -m "docs: 添加技术设计文档

- 系统架构说明
- API接口设计
- 数据流程图

Closes #010"
```

### 7.4 代码备份策略

比赛项目时间紧迫，代码安全尤为重要：

**多层备份策略**：

```
第一层：本地仓库
  - .git目录包含所有历史
  - 定期git commit保存进度
  - 每天至少提交一次

第二层：远程仓库
  - 推送到Gitee/GitHub
  - 即使电脑损坏也不丢
  - 确保队友有访问权限

第三层：重要版本标签
  - 每个关键节点打标签
  - 可以快速回溯到稳定版本
  - 初赛/复赛/决赛版本分开标记

第四层：定期导出
  - 重要时间点导出压缩包
  - 额外备份到百度网盘
  - 比赛前最终版本额外保存
```

**备份命令**：

```powershell
# 每天推送到远程（必须！）
git push origin develop

# 推送所有分支和标签
git push origin --all
git push origin --tags

# 导出重要版本
git archive -o backup-v1.0.0.zip --prefix=project/ v1.0.0-provincial

# 检查远程仓库状态
git remote -v
git fetch --all
git status
```

### 7.5 本章小结

本章中，我们通过一个完整的比赛项目案例，展示了Git在团队协作中的应用：

```
🏆 比赛场景实践
   - 三人团队分工协作
   - 从初始化到提交的完整流程
   - 版本标签管理
   
📄 文档管理
   - 使用单独的文档分支
   - 技术文档与代码分离
   
💾 备份策略
   - 多层备份
   - 定期推送
   - 重要版本导出
```

下一章，我们将学习Git的实用技巧，提高日常使用效率。

---

## 第八章：实用技巧与常见问题

### 8.1 Git配置优化

**别名配置**

为常用命令设置简短的别名：

```powershell
# 设置常用别名
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --'

# 设置美化输出
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

# 查看所有别名
git config --get-regexp alias
```

**使用前后对比**：

```powershell
# 配置前
git status
git checkout develop
git commit -m "feat: 添加新功能"

# 配置后
git st
git co develop
git ci -m "feat: 添加新功能"
```

### 8.2 暂存工作区

**场景**：正在开发新功能，突然要切换分支处理紧急问题

```powershell
# 1. 暂存当前修改（不提交）
git stash

# 输出：
# Saved working directory and index state WIP on feature/xxx:
#   src/main.py: 改动内容
#   ...

# 2. 切换到其他分支处理紧急问题
git checkout develop
# ... 处理紧急问题 ...
git commit -m "fix: 紧急修复..."
git push origin develop

# 3. 切回原分支
git checkout feature/xxx

# 4. 恢复暂存的工作
git stash pop

# 输出：
# Dropped refs/stacking...
```

**其他stash命令**：

```powershell
# 查看暂存列表
git stash list

# 输出示例：
# stash@{0}: WIP on feature/xxx: abc1234 feat: 添加功能A
# stash@{1}: WIP on feature/yyy: def5678 feat: 添加功能B

# 应用特定暂存
git stash apply stash@{1}

# 清除暂存
git stash drop stash@{0}

# 高级用法：
# 暂存包括未跟踪的文件
git stash -u

# 创建一个新分支并应用暂存
git stash branch new-branch-name

# 查看暂存的diff
git stash show -p
```

### 8.3 修改提交历史

**警告**：不要修改已推送的提交历史！

```powershell
# 修改最后一次提交信息
git commit --amend -m "新的提交信息"

# 修改最后一次提交（追加遗漏的文件）
git add forgotten-file.py
git commit --amend --no-edit

# 注意：会修改commit的hash值

# 变基整理多个提交
git rebase -i HEAD~3

# 交互式变基选项：
# pick = 保留该commit
# squash = 将该commit合并到上一个
# reword = 修改commit信息
# edit = 暂停进行修改
# drop = 删除该commit
```

**交互式变基示例**：

```bash
pick abc1234 feat: 添加功能A
squash def5678 fix: 修正A的bug
reword ghi8901 feat: 添加功能B
drop jkl2345 WIP: 工作进行中
```

执行后，abc1234和def5678会被合并为一个提交。

### 8.4 查找问题commit

**命令：git bisect - 二分查找问题**

当你发现某个版本有问题，但不知道是哪里引入的：

```powershell
# 1. 开始二分查找
git bisect start

# 2. 标记已知有问题的版本（当前版本）
git bisect bad

# 3. 标记正常的版本
git bisect good v1.0.0

# 4. Git自动checkout中间的版本
# 你测试该版本是否有问题

# 5. 标记结果
git bisect good  # 如果当前版本没问题
git bisect bad   # 如果当前版本有问题

# 6. Git继续查找，直到找到问题commit
# 输出：
# abc1234 is first bad commit
# commit abc1234
# Author: ...
# Message: ...

# 7. 结束查找
git bisect reset
```

**自动化bisect**：

```bash
# 编写测试脚本
#!/bin/bash
# test.sh
cd /path/to/project
make test
if [ $? -eq 0 ]; then
    exit 0  # 测试通过
else
    exit 1  # 测试失败
fi

# 使用自动化测试
git bisect start
git bisect bad
git bisect good v1.0.0
git bisect run ./test.sh
```

### 8.5 清理仓库

```powershell
# 删除已合并到main的分支（清理）
git branch --merged main | grep -v "main" | xargs git branch -d

# 清理无用的远程跟踪分支
git fetch --prune

# 清理未跟踪的文件（预览）
git clean -n

# 清理未跟踪的文件（执行）
git clean -f      # 删除未跟踪的文件
git clean -fd     # 删除未跟踪的文件和目录
git clean -fdx    # 清理所有，包括被忽略的文件

# 完整清理
git clean -fdx
```

### 8.6 忽略已被跟踪的文件

**问题**：文件已提交后，想添加到.gitignore但不生效

**解决方法**：

```powershell
# 1. 添加到.gitignore
echo "config.py" >> .gitignore

# 2. 从Git缓存中移除（不再跟踪）
git rm --cached config.py

# 3. 提交更改
git add .gitignore
git commit -m "chore: 移除config.py的跟踪"

# 如果想保留本地文件但停止跟踪
git rm --cached config.py
```

### 8.7 常见问题速查表

| 问题 | 解决方案 |
|------|---------|
| 误删了文件怎么恢复？ | `git checkout -- file` 或 `git restore file` |
| 想撤销上一次的提交？ | `git revert HEAD` 或 `git reset HEAD~1` |
| 文件误加入暂存区？ | `git reset HEAD file` |
| 想查看某个文件的修改历史？ | `git log -p -- file` |
| 两个分支冲突了怎么办？ | 手动编辑解决，`git add` 后 `git commit` |
| 忘记了commit的信息？ | `git log` 查看，或 `git commit --amend` |
| 想临时保存当前修改？ | `git stash` |
| 误操作导致丢失代码？ | `git reflog` 找回 |

### 8.8 本章小结

本章中，我们学习了一些Git的高级技巧：

```
⚡ 实用技巧
   - 命令别名配置
   - 暂存工作区（stash）
   - 修改提交历史
   - 二分查找问题（bisect）
   
🧹 仓库清理
   - 删除已合并的分支
   - 清理未跟踪的文件
   - 忽略已被跟踪的文件
   
📋 常见问题
   - 撤销、恢复、重置操作
   - 冲突处理方法
   - 代码找回
```

下一章，我们将总结全文，并提供进阶学习路线。

---

## 第九章：总结与进阶学习

### 9.1 核心命令回顾

**必须掌握的核心命令**：

```bash
# 基础操作
git init              # 初始化仓库
git clone             # 克隆仓库
git add               # 添加到暂存区
git commit            # 提交到仓库
git status            # 查看状态
git log               # 查看历史

# 分支操作
git branch            # 查看/创建分支
git checkout/git switch  # 切换分支
git merge             # 合并分支
git rebase            # 变基

# 远程操作
git remote            # 管理远程仓库
git push              # 推送到远程
git pull              # 拉取并合并
git fetch             # 仅拉取

# 高级操作
git stash             # 暂存工作
git bisect            # 二分查找问题
git cherry-pick       # 选择性合并
```

### 9.2 团队协作最佳实践

**给队长的建议**：

```
✅ 建立清晰的分支管理策略（Git Flow）
✅ 制定代码规范和提交流程
✅ 认真审查队友的Pull Request
✅ 保持develop分支的稳定
✅ 及时合并和清理已完成的分支
✅ 重要版本及时打标签
✅ 定期推送代码，不要等到最后一刻
✅ 遇到冲突不要慌，积极解决
```

**给队员的建议**：

```
✅ 从develop分支创建功能分支
✅ 功能完成后及时创建Pull Request
✅ 提交信息要清晰明了
✅ 定期拉取最新代码，减少冲突
✅ 保持分支小而专注
✅ 积极与队友沟通，避免重复劳动
✅ 遇到冲突先理解再解决，不要强行提交
✅ 重视代码审查，学习队友的优点
```

### 9.3 学习路线建议

**初级阶段**（第1-2周）

```
学习目标：掌握基础操作
- git init, clone, add, commit
- git status, log, diff
- 创建和使用分支
- 基本的合并操作

推荐资源：
- Pro Git（免费在线书）
- Git官方文档
- 官方交互式教程
```

**中级阶段**（第3-4周）

```
学习目标：掌握团队协作
- Git Flow工作流
- Pull Request流程
- 解决合并冲突
- 标签管理
- 基本的代码审查

推荐资源：
- GitHub官方教程
- Atlassian Git教程
- 实际参与团队项目
```

**高级阶段**（持续学习）

```
学习目标：熟练运用
- git bisect, cherry-pick
- 变基操作的高级用法
- 子模块管理
- Git钩子（Hooks）
- 自定义Git配置
- 理解Git内部原理

推荐资源：
- 官方文档深入阅读
- 参与开源项目学习
- Git源码阅读
```

### 9.4 Git进阶主题

以下主题可以作为后续学习的内容：

```
📚 子模块（Submodules）
   - 在一个仓库中引用另一个仓库
   - 适合管理第三方库
   
📚 Git钩子（Hooks）
   - 在特定操作时自动执行脚本
   - 自动化代码检查、格式化等
   
📚 Git内部原理
   - 对象模型
   - 引用和HEAD
   - 打包和传输协议
   
📚 自定义Git
   - 自定义命令
   - 配置高级选项
   - Git别名进阶
```

### 9.5 结语

恭喜你完成了《Git团队协作指南》的学习！

现在你掌握了：

```
✅ Git的核心概念和基本操作
✅ 分支管理的技巧
✅ 团队协作的完整流程
✅ 冲突处理的方法
✅ 比赛项目的实践案例
✅ 实用技巧和常见问题解决
```

记住几个关键点：

```
🎯 Git是工具，不是目的
   - Git是为了提高团队协作效率
   - 不要为了用Git而用Git
   
🎯 实践是最好的老师
   - 不要害怕犯错
   - Git给了你足够的"后悔药"
   - 多用、多练、多思考
   
🎯 团队协作比工具更重要
   - 良好的沟通比完美的工具链更重要
   - 代码审查是学习的好机会
   - 尊重队友，保持耐心
   
🎯 持续学习
   - Git的功能非常丰富
   - 随着项目复杂度提升，会遇到新问题
   - 持续学习，不断提升
```

现在开始使用Git管理你的比赛项目吧！无论是两人小队还是五人团队，Git都能帮助你更好地协作。

**祝你取得好成绩！** 🏆

---

## 附录：命令速查表

### A.1 基础命令速查

```bash
# 创建和初始化
git init                          # 初始化新仓库
git clone <url>                   # 克隆远程仓库
git clone <url> <folder-name>     # 克隆到指定文件夹

# 查看信息
git status                        # 查看工作区状态
git status -s                     # 简洁格式
git log                           # 查看提交历史
git log --oneline                 # 简洁一行格式
git log --graph                   # 图形化显示分支
git diff                          # 查看未暂存的变更
git diff --staged                 # 查看已暂存的变更
git show <commit>                  # 查看特定提交

# 基础操作
git add <file>                    # 添加文件到暂存区
git add .                          # 添加所有变更
git commit -m "message"           # 提交
git commit -am "message"          # 暂存并提交已跟踪文件

# 撤销操作
git checkout -- <file>            # 丢弃工作区修改
git reset HEAD <file>             # 取消暂存
git revert <commit>               # 创建新提交撤销指定提交
git reset --soft HEAD~1          # 撤销上次提交，保留修改
git reset --hard HEAD~1           # 撤销上次提交，丢弃修改
```

### A.2 分支命令速查

```bash
# 查看分支
git branch                        # 查看本地分支
git branch -a                     # 查看所有分支
git branch -v                     # 查看分支详情
git branch -d <branch>           # 删除已合并的分支
git branch -D <branch>           # 强制删除分支

# 创建和切换
git checkout <branch>              # 切换分支
git checkout -b <new-branch>     # 创建并切换
git switch <branch>               # 切换（新版）
git switch -c <new-branch>       # 创建并切换（新版）

# 合并
git merge <branch>                # 合并分支到当前分支
git merge --no-ff <branch>        # 禁用快速合并
git rebase <branch>              # 变基到目标分支
git rebase -i HEAD~3            # 交互式变基

# 标签
git tag                           # 查看标签
git tag <version>                 # 创建轻量标签
git tag -a <version> -m "msg"     # 创建附注标签
git tag -a <version> <commit>     # 给历史提交打标签
git push origin <tag>             # 推送标签
git push origin --tags            # 推送所有标签
```

### A.3 远程操作速查

```bash
# 远程仓库
git remote -v                     # 查看远程仓库
git remote add origin <url>      # 添加远程仓库
git remote remove origin         # 移除远程仓库

# 拉取和推送
git fetch                         # 拉取远程更新（不合并）
git pull                          # 拉取并合并
git push                          # 推送到远程
git push -u origin <branch>      # 首次推送，设置上游分支
git push origin --delete <branch> # 删除远程分支
```

### A.4 高级命令速查

```bash
# 暂存
git stash                         # 暂存当前工作
git stash list                    # 查看暂存列表
git stash pop                     # 恢复并删除暂存
git stash apply                   # 恢复暂存（保留）
git stash drop                    # 删除暂存

# 查找问题
git bisect start                 # 开始二分查找
git bisect bad                    # 标记有问题
git bisect good <commit>          # 标记没问题
git bisect reset                 # 结束查找

# 杂项
git cherry-pick <commit>         # 选择性合并提交
git reflog                       # 查看操作历史
git clean -f                     # 删除未跟踪文件
git clean -n                     # 预览删除（不实际删除）
```

---

## 参考资源

**官方文档**
- [Pro Git（中文版）](https://git-scm.com/book/zh/v2)
- [Git官方文档](https://git-scm.com/docs)

**在线学习**
- [GitHub Skills](https://skills.github.com/)
- [Atlassian Git教程](https://www.atlassian.com/git/tutorials)
- [Learn Git Branching](https://learngitbranching.js.org/)

**工具推荐**
- GUI工具：SourceTree、GitKraken、VS Code Git插件
- 终端：Windows Terminal + Git Bash
- 托管平台：GitHub（国际）、Gitee（国内）

---

**文章信息**
- 作者：刘航宇（河南工业大学人工智能协会）
- 发表于：2026年4月
- 最后更新：2026年4月23日