3969 lines
94 KiB
Markdown
3969 lines
94 KiB
Markdown
# 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日 |