Python 开发与 Git 工作流完整指南科学测试、安全修改、规范版本管理的全流程实践
Python 开发中的测试策略、代码修改规范、Git 分支管理、提交准则、协作流程、冲突解决与 CI 集成全覆盖
目录
一、核心原则:测试驱动与版本控制
❌ 随意开发(高风险)
# 无测试,直接在主分支修改 # 功能未验证就提交 # Commit 信息随意 # 多人同时改同一段代码 # 回退困难,Bug 难以追溯
代码质量不可控,Bug 流入生产环境,团队协作混乱。
✅ 规范工作流
# 先写测试,再写实现 # 功能分支开发,主干保护 # Commit 语义化,可追溯 # PR Review 合并代码 # CI 自动测试,发布有 Tag
每个变更可验证、可回滚、可审计,团队协作有序。
三大核心准则
测试先行 修改前先验证当前状态,修改后立即验证,测试通过才能提交
小步快跑 每个 Commit 只做一件事,便于 Review 和回滚,拒绝”大杂烩”提交
分支隔离 主分支永远可部署,开发在隔离分支进行,合并前强制 Review
二、科学测试方法论
2.1 测试金字塔
2.2 测试文件组织
project/ ├── src/ │ └── myapp/ │ ├── __init__.py │ ├── core.py │ └── utils.py ├── tests/ │ ├── __init__.py │ ├── unit/ # 单元测试 │ │ ├── test_core.py │ │ └── test_utils.py │ ├── integration/ # 集成测试 │ │ └── test_api.py │ └── conftest.py # pytest 共享 fixture ├── .github/workflows/ │ └── ci.yml └── pyproject.toml
2.3 pytest 最佳实践
安装测试框架
运行全部测试
带覆盖率
运行失败项
2.4 测试用例编写规范
# tests/unit/test_calculator.py
import pytest
from myapp.calculator import Calculator
class TestCalculator:
"""Calculator unit tests."""
def test_add_positive_numbers(self):
"""Test addition with positive numbers."""
calc = Calculator()
assert calc.add(2, 3) == 5
def test_add_negative_numbers(self):
"""Test addition with negative numbers."""
calc = Calculator()
assert calc.add(-2, -3) == -5
def test_divide_by_zero_raises(self):
"""Test division by zero raises ZeroDivisionError."""
calc = Calculator()
with pytest.raises(ZeroDivisionError):
calc.divide(10, 0)
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3),
(0, 0, 0),
(-1, 1, 0),
(100, -50, 50),
])
def test_add_parametrized(self, a, b, expected):
"""Test addition with multiple input sets."""
calc = Calculator()
assert calc.add(a, b) == expected
三、安全的代码修改策略
3.1 修改前准备
- 确认当前分支干净:
git status无未提交的修改 如果有临时修改,用git stash暂存或先提交 - 确认测试基线通过:
pytest全部通过 如果已有测试失败,先修复再开始新功能 - 创建功能分支:
git checkout -b feature/xxx分支名要语义化:feature/、fix/、refactor/ 前缀 - 编写失败的测试:先写测试,确认当前测试失败(TDD 红-绿-重构)
3.2 TDD 循环
3.3 代码质量工具链
代码格式化
代码检查
类型检查
安全扫描
3.4 pre-commit 配置
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0
hooks:
- id: mypy
additional_dependencies: [types-requests]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
# 安装 pre-commit 钩子 pip install pre-commit pre-commit install pre-commit installed at .git/hooks/pre-commit # 手动运行检查所有文件 pre-commit run --all-files
四、Git 分支管理模型
4.1 Git Flow 简化模型
main (protected) # 生产分支,永远可部署 │ ├─── develop # 开发集成分支(可选) │ │ │ ├─── feature/login # 功能分支:feature/xxx │ │ │ ├─── feature/auth # 功能分支:feature/xxx │ │ │ └─── fix/memory # 修复分支:fix/xxx │ └─── hotfix/security # 紧急修复:hotfix/xxx
分支命名规范
feature/xxx 新功能开发,从 main 检出
fix/xxx Bug 修复,从 main 检出
hotfix/xxx 紧急修复,从 main 检出,快速合并
refactor/xxx 代码重构,不改变行为
docs/xxx 文档更新
4.2 分支操作命令
# 创建并切换到功能分支 git checkout -b feature/user-authentication # 推送分支到远程 git push -u origin feature/user-authentication # 保持分支与 main 同步(rebase 方式,提交记录更整洁) git checkout feature/user-authentication git fetch origin git rebase origin/main # 功能完成后合并回 main git checkout main git pull origin main git merge --no-ff feature/user-authentication git push origin main
五、提交准则与 Commit Message
5.1 Conventional Commits 规范
<type>[optional scope]: <description> [optional body] [optional footer(s)]
| Type | 含义 | 示例 |
|---|---|---|
| feat | 新功能 | feat: 添加用户登录功能 |
| fix | Bug 修复 | fix: 修复空指针异常 |
| docs | 文档变更 | docs: 更新 API 使用说明 |
| style | 代码格式调整 | style: 格式化 core.py 缩进 |
| refactor | 代码重构 | refactor: 提取公共验证逻辑 |
| perf | 性能优化 | perf: 优化数据库查询 |
| test | 测试相关 | test: 添加单元测试覆盖 |
| chore | 构建/工具变更 | chore: 更新依赖版本 |
| ci | CI 配置变更 | ci: 添加 Python 3.13 测试 |
5.2 优秀 Commit 示例
feat(auth): add JWT-based authentication Implement JWT token generation and validation for user login. - Add /login endpoint returning access_token - Add token refresh mechanism - Add token blacklist for logout Closes #123 fix(api): handle missing parameters in /calculate endpoint Return 400 Bad Request instead of 500 when required parameters are missing. Add input validation before processing. BREAKING CHANGE: error response format changed from plain text to JSON with "detail" field. test(calculator): add edge case tests for division - Test division by zero raises ZeroDivisionError - Test float division precision - Test negative number division
六、协作开发与 Pull Request
6.1 PR 创建规范
- 功能开发完成,本地测试全部通过
- 推送分支到远程:
git push origin feature/xxx - 在 GitHub/GitLab 创建 Pull Request 标题格式:[类型] 简要描述,如 “[feat] 添加用户认证模块”
- 填写 PR 描述模板: – 变更内容:做了什么 – 测试覆盖:新增/修改了哪些测试 – 影响范围:是否涉及 API 变更 – 关联 Issue:Fixes #xxx
- 添加 Reviewer,等待代码审查
6.2 PR 描述模板
## 变更内容 - 添加用户 JWT 认证模块 - 实现 /login 和 /refresh 端点 ## 测试覆盖 - [x] 单元测试:新增 12 个测试用例 - [x] 集成测试:验证完整登录流程 - [x] 手动测试:Postman 验证 API ## 影响范围 - 无破坏性变更 - 新增环境变量 JWT_SECRET ## 关联 Issue Fixes #123 Closes #124 ## 截图(如适用)
6.3 代码审查 Checklist
Reviewer 审查清单
✅ 代码逻辑是否正确,边界条件是否考虑
✅ 是否有对应的测试覆盖,测试是否有效
✅ 是否引入了不必要的依赖
✅ 代码风格是否一致,命名是否清晰
✅ 是否存在安全隐患(SQL 注入、越权等)
✅ 性能是否可接受(N+1 查询、大对象内存等)
✅ 文档是否同步更新
七、冲突解决与代码审查
7.1 冲突预防策略
预防冲突
1. 小步提交,减少冲突范围
2. 频繁同步 main 分支到特性分支
3. 避免多人同时修改同一份大文件
4. 使用功能模块划分,降低耦合
冲突处理
1. 先确认自己版本还是对方版本正确
2. 不要简单保留双方,要理解逻辑
3. 冲突解决后必须重新测试
4. 冲突解决单独作为一个 Commit
7.2 冲突解决流程
# 尝试合并 main 到当前分支 git merge origin/main Auto-merging src/core.py CONFLICT (content): Merge conflict in src/core.py Automatic merge failed; fix conflicts and then commit the result. # 查看冲突文件 git status Unmerged paths: (use "git add <file>..." to mark resolution) both modified: src/core.py # 编辑冲突文件,解决冲突标记 # <<<<<<< HEAD # 你的代码 # ======= # 对方代码 # >>>>>>> main # 标记冲突已解决 git add src/core.py git commit -m "merge: resolve conflict in core.py"
7.3 请求变更与回复
# 审查者提出意见
Comment on line 42:
> 建议将这里的魔法数字提取为常量
> MAGIC_NUMBER = 100
# 开发者回复并修改
Reply: 已修改,提取为 MAX_RETRY_COUNT = 3
# 开发者推送修改
git add src/core.py
git commit --amend --no-edit
git push --force-with-lease origin feature/xxx
八、版本发布与 Tag 管理
8.1 发布流程
8.2 Tag 操作
# 附注标签(推荐,包含签名信息) git tag -a v1.2.0 -m "Release version 1.2.0" git push origin v1.2.0 # 轻量标签(仅引用,不推荐用于发布) git tag v1.2.0 git push origin v1.2.0 # 查看标签列表 git tag -l "v1.*" # 删除本地标签 git tag -d v1.2.0
8.3 CHANGELOG 驱动发布
# 发布前更新 CHANGELOG.md ## [1.2.0] - 2026-07-15 ### Added - 添加用户认证模块 (feat: auth) - 支持批量导出功能 ### Changed - 优化数据库查询性能 30% ### Fixed - 修复内存泄漏问题 (fix: memory) - 修复并发下的竞态条件 ### Security - 升级依赖库修复 CVE-2026-xxx
九、CI/CD 自动化测试
9.1 GitHub Actions 完整配置
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
lint-and-test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Lint with ruff
run: ruff check src/ tests/
- name: Type check with mypy
run: mypy src/
- name: Test with pytest
run: pytest --cov=src --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
fail_ci_if_error: false
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: {python-version: "3.12"}
- run: pip install bandit safety
- run: bandit -r src/
- run: safety check
9.2 分支保护规则
main 分支保护配置(GitHub)
✅ Require pull request reviews:至少 1 人 Review 才能合并
✅ Require status checks:CI 通过才能合并
✅ Require conversation resolution:所有对话解决才能合并
✅ Require signed commits(可选):要求提交签名
✅ Restrict pushes:禁止直接推送到 main
十、常见问题与应急预案
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
| 误提交到 main | 未创建分支直接修改 | git revert HEAD 回滚,或 git reset –soft HEAD~1 后切分支重新提交 |
| 提交包含敏感信息 | 误将密码/API Key 写入代码 | git filter-repo 清理历史,轮换密钥,切勿只 git rm |
| 本地测试通过 CI 失败 | 环境差异、依赖版本不同 | 使用 requirements.txt 锁定版本,清理本地缓存重新安装 |
| 合并后 main 测试失败 | 分支合并产生冲突未解决 | 立即 revert 合并提交,修复后重新 PR |
| 提交记录混乱 | 多次小修小补的提交 | git rebase -i HEAD~N 合并为清晰的提交,或在合并时 squash |
| 忘记写测试 | 赶进度跳过测试 | CI 强制覆盖率阈值,pre-commit 阻止无测试提交 |
| 代码冲突频繁 | 分支存在时间过长 | 每天 rebase main,功能拆分更细,小步快跑 |
应急回滚操作
# 场景1:刚 push 到远程,想撤销最后一次提交 git revert HEAD git push origin main # 场景2:发现 main 有严重 Bug,需要紧急回滚到上一个版本 git log --oneline -5 abc1234 (HEAD -> main) 错误提交 def5678 上一个稳定版本 git revert abc1234 git push origin main # 场景3:本地回滚到某个提交(未 push) git reset --soft HEAD~1 # 保留修改到暂存区 git reset --mixed HEAD~1 # 保留修改到工作区 git reset --hard HEAD~1 # 完全丢弃修改(慎用)
Python Dev & Git Workflow Complete GuideScientific Testing, Safe Changes & Version Control Best Practices
Testing strategies, code modification practices, Git branching, commit conventions, collaboration, conflict resolution & CI integration
Table of Contents
1 Core Principles
Three Core Rules
Test First Verify current state before changes, verify immediately after, commit only when tests pass
Small Steps Each commit does one thing only, easy to review and revert, no “kitchen sink” commits
Branch Isolation Main branch always deployable, development on isolated branches, mandatory review before merge
2 Scientific Testing Methodology
Testing Pyramid
pytest Best Practices
import pytest
from myapp.calculator import Calculator
class TestCalculator:
def test_add_positive_numbers(self):
calc = Calculator()
assert calc.add(2, 3) == 5
def test_divide_by_zero_raises(self):
calc = Calculator()
with pytest.raises(ZeroDivisionError):
calc.divide(10, 0)
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3), (0, 0, 0), (-1, 1, 0),
])
def test_add_parametrized(self, a, b, expected):
calc = Calculator()
assert calc.add(a, b) == expected
3 Safe Code Modification
TDD Cycle
Code Quality Toolchain
Format
Lint
Type Check
Security
4 Git Branching Model
main (protected) # Production branch, always deployable │ ├─── feature/login # Feature branches: feature/xxx │ ├─── feature/auth │ ├─── fix/memory # Fix branches: fix/xxx │ └─── hotfix/security # Hotfix branches: hotfix/xxx
5 Commit Conventions
Conventional Commits
| Type | Meaning | Example |
|---|---|---|
| feat | New feature | feat: add user login |
| fix | Bug fix | fix: handle null pointer |
| docs | Documentation | docs: update API guide |
| refactor | Code refactor | refactor: extract validator |
| test | Tests | test: add edge case tests |
| chore | Tooling | chore: update dependencies |
6 Collaboration & Pull Requests
PR Description Template
## Changes - Add JWT authentication module - Implement /login and /refresh endpoints ## Test Coverage - [x] Unit tests: 12 new cases - [x] Integration tests: full login flow - [x] Manual test: Postman verification ## Breaking Changes None ## Related Issues Fixes #123
Code Review Checklist
Reviewer Checklist
✅ Logic correctness and edge cases
✅ Test coverage adequacy
✅ No unnecessary dependencies
✅ Consistent style, clear naming
✅ Security review (injection, authorization)
✅ Performance acceptable
✅ Documentation updated
7 Conflict Resolution
# Sync main to feature branch (rebase for clean history) git fetch origin git rebase origin/main # Resolve conflicts in files # Edit conflict markers <<<<<<< ======= >>>>>>> git add <resolved-files> git rebase --continue
8 Version Releases & Tags
Release Flow
# Create annotated tag git tag -a v1.2.0 -m "Release version 1.2.0" git push origin v1.2.0
9 CI/CD Automation
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: {python-version: "${{ matrix.python-version }}"}
- run: pip install -e ".[dev]"
- run: ruff check src/
- run: mypy src/
- run: pytest --cov=src --cov-report=xml
10 FAQ & Emergency Procedures
| Issue | Solution |
|---|---|
| Committed to main by mistake | git revert HEAD, or git reset –soft HEAD~1 and redo on feature branch |
| Committed secrets | git filter-repo to rewrite history, rotate credentials immediately |
| Local tests pass, CI fails | Lock dependencies with requirements.txt, clean and reinstall |
| Main broken after merge | Revert the merge commit immediately, fix and re-PR |
| Messy commit history | git rebase -i HEAD~N to squash, or squash on merge |
| Frequent conflicts | Rebase main daily, split features smaller |
Emergency Rollback
# Revert last pushed commit git revert HEAD git push origin main # Local undo (not yet pushed) git reset --soft HEAD~1 # Keep changes staged git reset --hard HEAD~1 # Discard completely (careful!)
