跳转至

05 - 版本控制

学习时间: 3-4小时 重要性: ⭐⭐⭐⭐⭐ 团队协作必备


🎯 学习目标

  • 理解Git的核心概念和工作原理
  • 掌握常用Git命令和工作流程
  • 学会分支管理和冲突解决
  • 了解GitHub/GitLab协作流程
  • 掌握.gitignore配置

1. Git基础概念

1.1 什么是版本控制?

版本控制是一种记录文件变化,以便将来查阅特定版本修订情况的系统。

为什么需要版本控制?

Text Only
场景1: 你正在写一个报告,保存了多个版本
- report_v1.docx
- report_v2_final.docx
- report_v3_final_final.docx
- report_v4_final_final_really.docx

问题: 不知道哪个是最新版,不知道改了什么

场景2: 团队协作
- 小明修改了第10行
- 小红同时修改了第10行
- 合并时不知道用谁的版本

Git解决方案: - ✅ 完整的历史记录 - ✅ 清晰的版本对比 - ✅ 自动合并(大部分情况) - ✅ 并行开发支持

1.2 Git核心概念

Text Only
工作区 (Working Directory)
    ↓ git add
暂存区 (Staging Area / Index)
    ↓ git commit
本地仓库 (Local Repository)
    ↓ git push
远程仓库 (Remote Repository)

三个区域的含义: - 工作区: 你实际看到的文件 - 暂存区: 准备提交的更改 - 仓库: 永久保存的提交历史


2. Git基础命令

2.1 配置Git

Bash
# 设置用户名和邮箱(必须)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

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

# 设置默认分支名
git config --global init.defaultBranch main

# 查看配置
git config --list
git config user.name

# 配置别名(快捷命令)
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 st 代替 git status

2.2 仓库操作

Bash
# 初始化新仓库
git init

# 克隆远程仓库
git clone https://github.com/username/repo.git
git clone https://github.com/username/repo.git my-folder  # 指定目录名

# 查看远程仓库
git remote -v

# 添加远程仓库
git remote add origin https://github.com/username/repo.git

# 修改远程仓库URL
git remote set-url origin https://github.com/username/new-repo.git

2.3 基本工作流程

Bash
# 1. 查看状态
git status

# 2. 添加文件到暂存区
git add filename.txt          # 添加单个文件
git add .                     # 添加所有更改
git add *.py                  # 添加所有Python文件
git add -A                    # 添加所有更改(包括删除)

# 3. 提交更改
git commit -m "描述性提交信息"

# 4. 推送到远程
git push origin main

# 完整示例
git add .
git commit -m "添加用户认证功能"
git push origin main

2.4 查看历史

Bash
# 查看提交历史
git log
git log --oneline                    # 简洁显示
git log --graph                      # 图形化显示分支
git log --oneline --graph --all      # 组合使用
git log -5                           # 最近5条
git log --author="username"          # 按作者筛选

# 查看工作区与暂存区的差异
git diff
git diff filename.txt

# 查看暂存区与最后一次提交的差异
git diff --staged
git diff --cached

# 查看某次提交的详情
git show commit-hash
git show HEAD                        # 查看最新提交
git show HEAD~1                      # 查看倒数第二次提交

2.5 撤销操作

Bash
# 撤销工作区的修改(未add)
git checkout -- filename.txt
git restore filename.txt             # Git 2.23+

# 撤销暂存区的修改(已add未commit)
git reset HEAD filename.txt
git restore --staged filename.txt    # Git 2.23+

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

# 回退到指定版本(保留修改)
git reset --soft HEAD~1

# 回退到指定版本(丢弃修改)
git reset --hard commit-hash

# 查看所有操作记录(用于恢复)
git reflog

3. 分支管理

3.1 分支基础

Bash
# 查看分支
git branch                           # 本地分支
git branch -r                        # 远程分支
git branch -a                        # 所有分支

# 创建分支
git branch feature-x                 # 创建分支
git checkout -b feature-x            # 创建并切换
git switch -c feature-x              # 新命令(Git 2.23+)

# 切换分支
git checkout main
git switch main                      # 新命令(Git 2.23+)

# 删除分支
git branch -d feature-x              # 已合并的分支
git branch -D feature-x              # 强制删除

# 重命名分支
git branch -m old-name new-name

3.2 合并分支

Bash
# 合并分支到当前分支
git checkout main
git merge feature-x

# 合并策略
# 1. Fast-forward(快进合并)
#    main: A---B
#    feature-x: A---B---C---D
#    合并后: A---B---C---D

# 2. Three-way merge(三方合并)
#    main: A---B---C
#    feature-x: A---B---D---E
#    合并后: A---B---C---F---D---E (F是合并提交)

# 禁用快进合并(保留分支历史)
git merge --no-ff feature-x

3.3 分支工作流示例

Bash
# 1. 从main创建功能分支
git checkout main
git pull origin main
git checkout -b feature-login

# 2. 开发功能
echo "开发代码..."
git add .
git commit -m "实现登录功能"

# 3. 开发过程中同步main的更新
git checkout main
git pull origin main
git checkout feature-login
git rebase main                    # 或者 git merge main

# 4. 完成功能,合并到main
git checkout main
git merge feature-login
git push origin main

# 5. 删除功能分支
git branch -d feature-login
git push origin --delete feature-login

4. 分支策略

4.1 Git Flow

Git Flow是一种经典的分支模型,适合有明确发布周期的项目。

Text Only
main (生产分支)
develop (开发分支)
  ↑    ↑
feature  feature (功能分支)
release (发布分支)
hotfix (热修复分支)

分支说明: - main: 生产环境代码 - develop: 开发分支,集成所有功能 - feature/: 功能分支,从develop创建 - release/: 发布分支,从develop创建 - hotfix/*: 热修复分支,从main创建

Bash
# Git Flow初始化
git flow init

# 创建功能分支
git flow feature start my-feature
# 完成功能
git flow feature finish my-feature

# 创建发布分支
git flow release start 1.0.0
# 完成发布
git flow release finish 1.0.0

# 创建热修复
git flow hotfix start fix-bug
# 完成热修复
git flow hotfix finish fix-bug

4.2 GitHub Flow

GitHub Flow是一种简化的分支模型,适合持续部署的项目。

Text Only
main
feature-branch (Pull Request)

工作流程: 1. 从main创建分支 2. 提交更改 3. 创建Pull Request 4. 代码审查和讨论 5. 合并到main 6. 部署

4.3 Trunk-Based Development

所有开发都在main分支进行,使用特性开关控制功能。

Bash
# 短生命周期的特性分支(<1天)
git checkout -b quick-fix
git commit -am "Quick fix"
git checkout main
git merge quick-fix

5. 冲突解决

5.1 什么是冲突?

当两个人修改了同一文件的同一部分,Git无法自动合并时就会产生冲突。

Text Only
场景:
小明: A---B---C (修改了第10行)
小红: A---B---D (也修改了第10行)

合并时Git不知道用哪个版本

5.2 解决冲突

Bash
# 尝试合并
git merge feature-x
# Auto-merging file.txt
# CONFLICT (content): Merge conflict in file.txt
# Automatic merge failed; fix conflicts and then commit the result.

# 查看冲突文件
git status

# 打开冲突文件,会看到类似这样的内容:
<<<<<<< HEAD
这是main分支的内容
=======
这是feature-x分支的内容
>>>>>>> feature-x

# 手动编辑,保留需要的代码,删除标记
# 例如:
这是合并后的内容

# 标记为已解决
git add file.txt
git commit -m "解决合并冲突"

# 或者放弃合并
git merge --abort

5.3 预防冲突

Bash
# 1. 经常同步主分支
git pull origin main

# 2. 使用rebase保持线性历史
git checkout feature-x
git rebase main

# 3. 小步提交,频繁推送
# 4. 沟通协作,避免同时修改同一文件

6. 远程协作

6.1 Pull Request / Merge Request

工作流程:

Bash
# 1. Fork仓库(如果是外部贡献者)

# 2. 克隆仓库
git clone https://github.com/your-username/repo.git

# 3. 创建分支
git checkout -b feature-awesome

# 4. 提交更改
git add .
git commit -m "添加 awesome 功能"
git push origin feature-awesome

# 5. 在GitHub/GitLab上创建Pull Request

# 6. 代码审查
#    - 审查者提出意见
#    - 作者修改代码
#    - 再次推送,PR自动更新

# 7. 合并PR
#    - 通过审查后合并到main

6.2 同步上游仓库

Bash
# 添加上游仓库
git remote add upstream https://github.com/original-owner/original-repo.git

# 获取上游更新
git fetch upstream

# 合并到本地main
git checkout main
git merge upstream/main

# 推送到自己的fork
git push origin main

6.3 代码审查清单

提交PR前自查: - [ ] 代码能正常运行 - [ ] 添加了必要的测试 - [ ] 更新了文档 - [ ] 遵循代码规范 - [ ] 提交信息清晰 - [ ] 没有调试代码(print, debugger等)


7. .gitignore配置

7.1 基本语法

Text Only
# 注释
*.log                  # 忽略所有.log文件
temp/                  # 忽略temp目录
build/                 # 忽略build目录
!important.log         # 不忽略important.log
*.py[cod]              # 忽略.pyc, .pyo, .pyd
**/__pycache__/        # 忽略所有__pycache__目录

7.2 Python项目.gitignore

Text Only
# 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

# Virtual environments
venv/
ENV/
env/
.venv

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

# Jupyter
.ipynb_checkpoints

# Environment variables
.env
.env.local

# Logs
*.log

# OS
.DS_Store
Thumbs.db

7.3 常用模板

GitHub提供了各种语言的.gitignore模板: https://github.com/github/gitignore

Bash
# 使用gitignore.io生成
curl -o .gitignore https://www.toptal.com/developers/gitignore/api/python,pycharm,windows,macos,linux <!-- ⚠️ 可能需要登录 -->

8. 高级技巧

8.1 储藏(Stash)

Bash
# 储藏当前更改
git stash
git stash push -m "描述信息"

# 查看储藏列表
git stash list

# 应用最近的储藏
git stash pop          # 应用并删除
git stash apply        # 应用但不删除

# 应用指定的储藏
git stash apply stash@{2}

# 删除储藏
git stash drop stash@{0}
git stash clear        # 清空所有

8.2 拣选(Cherry-pick)

Bash
# 将某个提交应用到当前分支
git cherry-pick commit-hash

# 拣选多个提交
git cherry-pick A^..B  # A到B的所有提交

# 拣选时解决冲突
git cherry-pick --continue
git cherry-pick --abort

8.3 变基(Rebase)

Bash
# 交互式变基
git rebase -i HEAD~3   # 最近3个提交

# 常用操作:
# p, pick = 使用提交
# r, reword = 修改提交信息
# e, edit = 修改提交内容
# s, squash = 合并到上一个提交
# d, drop = 删除提交

# 变基时解决冲突
git rebase --continue
git rebase --abort

# 不要对已经推送到远程的提交进行变基!

8.4 子模块

Bash
# 添加子模块
git submodule add https://github.com/user/repo.git path/to/submodule

# 克隆包含子模块的仓库
git clone --recurse-submodules https://github.com/user/main-repo.git

# 更新子模块
git submodule update --init --recursive

📝 练习

练习1: 基础操作

Bash
# 1. 创建一个新仓库
mkdir my-project
cd my-project
git init

# 2. 创建文件并提交
echo "Hello Git" > README.md
git add README.md
git commit -m "Initial commit"

# 3. 修改文件并查看差异
echo "World" >> README.md
git diff
git add .
git commit -m "Add world"

# 4. 查看历史
git log --oneline

练习2: 分支操作

Bash
# 1. 创建并切换到新分支
git checkout -b feature-1

# 2. 在新分支上提交更改
echo "Feature 1" > feature.txt
git add .
git commit -m "Add feature 1"

# 3. 切换回main分支
git checkout main

# 4. 合并分支
git merge feature-1

# 5. 删除分支
git branch -d feature-1

练习3: 解决冲突

Bash
# 1. 创建两个分支,修改同一文件
git checkout -b branch-a
echo "Branch A content" > conflict.txt
git add . && git commit -m "Branch A"

git checkout main
git checkout -b branch-b
echo "Branch B content" > conflict.txt
git add . && git commit -m "Branch B"

# 2. 尝试合并,会产生冲突
git checkout main
git merge branch-a
git merge branch-b  # 冲突!

# 3. 手动解决冲突,完成合并

练习4: GitHub协作

Bash
# 1. 在GitHub上fork一个仓库

# 2. 克隆fork的仓库
git clone https://github.com/your-username/forked-repo.git

# 3. 添加上游仓库
git remote add upstream https://github.com/original-owner/original-repo.git

# 4. 创建分支,修改代码,提交PR

# 5. 同步上游更新
git fetch upstream
git merge upstream/main

🎯 自我检查

  • 理解Git的三个工作区域
  • 掌握基本的Git命令(add, commit, push, pull)
  • 会使用分支进行并行开发
  • 理解并能解决合并冲突
  • 了解Git Flow和GitHub Flow工作流
  • 会配置.gitignore文件
  • 理解Pull Request流程
  • 会使用stash储藏更改

📚 延伸阅读


🎉 恭喜完成阶段5!

你已经完成了工程最佳实践的学习!

你掌握了: - 虚拟环境管理 - 代码调试技巧 - 单元测试 - 代码规范 - 版本控制

下一步: 进入实战练习巩固所学知识。