跳转至

Git 工作流模式

Git 版本控制、分支策略和协作开发的最佳实践。

何时激活

  • 为新项目设置 Git 工作流
  • 决定分支策略(GitFlow、主干开发、GitHub Flow)
  • 编写提交信息和 PR 描述
  • 解决合并冲突
  • 管理发布和版本标签
  • 让新团队成员熟悉 Git 实践

分支策略

最适合持续部署和中小型团队。

main (protected, always deployable)
  │
  ├── feature/user-auth      → PR → merge to main
  ├── feature/payment-flow   → PR → merge to main
  └── fix/login-bug          → PR → merge to main

规则: - main 始终可部署 - 从 main 创建功能分支 - 准备好审查时打开 Pull Request - 在审批通过且 CI 通过后,合并到 main - 合并后立即部署

主干开发(高速度团队){#trunk-based-development-high-velocity-teams}

最适合拥有强大 CI/CD 和功能开关的团队。

main (trunk)
  │
  ├── short-lived feature (1-2 days max)
  ├── short-lived feature
  └── short-lived feature

规则: - 所有人都提交到 main 或短期分支 - 功能开关隐藏未完成的工作 - CI 必须在合并前通过 - 每天部署多次

GitFlow(复杂,以发布周期驱动){#gitflow-complex-release-cycle-driven}

最适合计划性发布和企业项目。

main (production releases)
  │
  └── develop (integration branch)
        │
        ├── feature/user-auth
        ├── feature/payment
        │
        ├── release/1.0.0    → merge to main and develop
        │
        └── hotfix/critical  → merge to main and develop

规则: - main 只包含生产就绪代码 - develop 是集成分支 - 功能分支从 develop 创建,合并回 develop - 发布分支从 develop 创建,合并到 main 和 develop - 热修复分支从 main 创建,合并到 main 和 develop

何时使用哪种策略

策略 团队规模 发布频率 最适合
GitHub Flow 任意 持续 SaaS、Web 应用、初创公司
主干开发 5 人以上且有经验 每天多次 高速度团队、功能开关
GitFlow 10 人以上 计划性 企业、受监管行业

提交信息

约定式提交格式

<type>(<scope>): <subject>

[optional body]

[optional footer(s)]

类型

类型 用途 示例
feat 新功能 feat(auth): add OAuth2 login
fix 缺陷修复 fix(api): handle null response in user endpoint
docs 文档 docs(readme): update installation instructions
style 格式调整,无代码变更 style: fix indentation in login component
refactor 代码重构 refactor(db): extract connection pool to module
test 添加/更新测试 test(auth): add unit tests for token validation
chore 维护任务 chore(deps): update dependencies
perf 性能改进 perf(query): add index to users table
ci CI/CD 变更 ci: add PostgreSQL service to test workflow
revert 回滚之前的提交 revert: revert "feat(auth): add OAuth2 login"

好示例与坏示例

# BAD: Vague, no context
git commit -m "fixed stuff"
git commit -m "updates"
git commit -m "WIP"

# GOOD: Clear, specific, explains why
git commit -m "fix(api): retry requests on 503 Service Unavailable

The external API occasionally returns 503 errors during peak hours.
Added exponential backoff retry logic with max 3 attempts.

Closes #123"

提交信息模板

在仓库根目录创建 .gitmessage:

# <type>(<scope>): <subject>
# # Types: feat, fix, docs, style, refactor, test, chore, perf, ci, revert
# Scope: api, ui, db, auth, etc.
# Subject: imperative mood, no period, max 50 chars
#
# [optional body] - explain why, not what
# [optional footer] - Breaking changes, closes #issue

通过以下命令启用:git config commit.template .gitmessage

合并与变基

合并(保留历史){#merge-preserves-history}

# Creates a merge commit
git checkout main
git merge feature/user-auth

# Result:
# *   merge commit
# |\
# | * feature commits
# |/
# * main commits

适用场景: - 将功能分支合并到 main - 你想保留完整的历史记录 - 多人协作过该分支 - 分支已被推送,其他人可能基于它开发

变基(线性历史){#rebase-linear-history}

# Rewrites feature commits onto target branch
git checkout feature/user-auth
git rebase main

# Result:
# * feature commits (rewritten)
# * main commits

适用场景: - 用最新的 main 更新本地功能分支 - 你想要线性、干净的历史 - 分支仅存在于本地(未推送) - 只有你一个人在该分支上工作

变基工作流

# Update feature branch with latest main (before PR)
git checkout feature/user-auth
git fetch origin
git rebase origin/main

# Fix any conflicts
# Tests should still pass

# Force push (only if you're the only contributor)
git push --force-with-lease origin feature/user-auth

何时不应变基

# NEVER rebase branches that:
- Have been pushed to a shared repository
- Other people have based work on
- Are protected branches (main, develop)
- Are already merged

# Why: Rebase rewrites history, breaking others' work

Pull Request 工作流

PR 标题格式

<type>(<scope>): <description>

Examples:
feat(auth): add SSO support for enterprise users
fix(api): resolve race condition in order processing
docs(api): add OpenAPI specification for v2 endpoints

PR 描述模板

## What

Brief description of what this PR does.

## Why

Explain the motivation and context.

## How

Key implementation details worth highlighting.

## Testing

- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing performed

## Screenshots (if applicable)

Before/after screenshots for UI changes.

## Checklist

- [ ] Code follows project style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex logic
- [ ] Documentation updated
- [ ] No new warnings introduced
- [ ] Tests pass locally
- [ ] Related issues linked

Closes #123

代码审查清单

致审查者:

  • [ ] 代码是否解决了所述问题?
  • [ ] 是否有未处理的边界情况?
  • [ ] 代码是否可读且易于维护?
  • [ ] 是否有足够的测试?
  • [ ] 是否存在安全隐患?
  • [ ] 提交历史是否干净(如有需要是否已压缩)?

致作者:

  • [ ] 在请求审查前完成自我审查
  • [ ] CI 通过(测试、lint、typecheck)
  • [ ] PR 规模合理(理想情况下少于 500 行)
  • [ ] 与单一功能/修复相关
  • [ ] 描述清楚解释了变更内容

冲突解决

识别冲突

# Check for conflicts before merge
git checkout main
git merge feature/user-auth --no-commit --no-ff

# If conflicts, Git will show:
# CONFLICT (content): Merge conflict in src/auth/login.ts
# Automatic merge failed; fix conflicts and then commit the result.

解决冲突

# See conflicted files
git status

# View conflict markers in file
# <<<<<<< HEAD
# content from main
# =======
# content from feature branch
# >>>>>>> feature/user-auth

# Option 1: Manual resolution
# Edit file, remove markers, keep correct content

# Option 2: Use merge tool
git mergetool

# Option 3: Accept one side
git checkout --ours src/auth/login.ts    # Keep main version
git checkout --theirs src/auth/login.ts  # Keep feature version

# After resolving, stage and commit
git add src/auth/login.ts
git commit

冲突预防策略

# 1. Keep feature branches small and short-lived
# 2. Rebase frequently onto main
git checkout feature/user-auth
git fetch origin
git rebase origin/main

# 3. Communicate with team about touching shared files
# 4. Use feature flags instead of long-lived branches
# 5. Review and merge PRs promptly

分支管理

命名约定

# Feature branches
feature/user-authentication
feature/JIRA-123-payment-integration

# Bug fixes
fix/login-redirect-loop
fix/456-null-pointer-exception

# Hotfixes (production issues)
hotfix/critical-security-patch
hotfix/database-connection-leak

# Releases
release/1.2.0
release/2024-01-hotfix

# Experiments/POCs
experiment/new-caching-strategy
poc/graphql-migration

分支清理

# Delete local branches that are merged
git branch --merged main | grep -v "^\*\|main" | xargs -n 1 git branch -d

# Delete remote-tracking references for deleted remote branches
git fetch -p

# Delete local branch
git branch -d feature/user-auth  # Safe delete (only if merged)
git branch -D feature/user-auth  # Force delete

# Delete remote branch
git push origin --delete feature/user-auth

暂存工作流

# Save work in progress
git stash push -m "WIP: user authentication"

# List stashes
git stash list

# Apply most recent stash
git stash pop

# Apply specific stash
git stash apply stash@{2}

# Drop stash
git stash drop stash@{0}

发布管理

语义化版本

MAJOR.MINOR.PATCH

MAJOR: Breaking changes
MINOR: New features, backward compatible
PATCH: Bug fixes, backward compatible

Examples:
1.0.0 → 1.0.1 (patch: bug fix)
1.0.1 → 1.1.0 (minor: new feature)
1.1.0 → 2.0.0 (major: breaking change)

创建发布

# Create annotated tag
git tag -a v1.2.0 -m "Release v1.2.0

Features:
- Add user authentication
- Implement password reset

Fixes:
- Resolve login redirect issue

Breaking Changes:
- None"

# Push tag to remote
git push origin v1.2.0

# List tags
git tag -l

# Delete tag
git tag -d v1.2.0
git push origin --delete v1.2.0

生成变更日志

# Generate changelog from commits
git log v1.1.0..v1.2.0 --oneline --no-merges

# Or use conventional-changelog
npx conventional-changelog -i CHANGELOG.md -s

Git 配置

基本配置

# User identity
git config --global user.name "Your Name"
git config --global user.email "your@email.com"

# Default branch name
git config --global init.defaultBranch main

# Pull behavior (rebase instead of merge)
git config --global pull.rebase true

# Push behavior (push current branch only)
git config --global push.default current

# Auto-correct typos
git config --global help.autocorrect 1

# Better diff algorithm
git config --global diff.algorithm histogram

# Color output
git config --global color.ui auto

实用别名

# Add to ~/.gitconfig
[alias]
    co = checkout
    br = branch
    ci = commit
    st = status
    unstage = reset HEAD --
    last = log -1 HEAD
    visual = log --oneline --graph --all
    amend = commit --amend --no-edit
    wip = commit -m "WIP"
    undo = reset --soft HEAD~1
    contributors = shortlog -sn

Gitignore 模式

# Dependencies
node_modules/
vendor/

# Build outputs
dist/
build/
*.o
*.exe

# Environment files
.env
.env.local
.env.*.local

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

# OS files
.DS_Store
Thumbs.db

# Logs
*.log
logs/

# Test coverage
coverage/

# Cache
.cache/
*.tsbuildinfo

常见工作流

开始新功能

# 1. Update main branch
git checkout main
git pull origin main

# 2. Create feature branch
git checkout -b feature/user-auth

# 3. Make changes and commit
git add .
git commit -m "feat(auth): implement OAuth2 login"

# 4. Push to remote
git push -u origin feature/user-auth

# 5. Create Pull Request on GitHub/GitLab

使用新更改更新 PR

# 1. Make additional changes
git add .
git commit -m "feat(auth): add error handling"

# 2. Push updates
git push origin feature/user-auth

将 Fork 与上游同步

# 1. Add upstream remote (once)
git remote add upstream https://github.com/original/repo.git

# 2. Fetch upstream
git fetch upstream

# 3. Merge upstream/main into your main
git checkout main
git merge upstream/main

# 4. Push to your fork
git push origin main

撤销错误

# Undo last commit (keep changes)
git reset --soft HEAD~1

# Undo last commit (discard changes)
git reset --hard HEAD~1

# Undo last commit pushed to remote
git revert HEAD
git push origin main

# Undo specific file changes
git checkout HEAD -- path/to/file

# Fix last commit message
git commit --amend -m "New message"

# Add forgotten file to last commit
git add forgotten-file
git commit --amend --no-edit

Git 钩子

预提交钩子

#!/bin/bash
# .git/hooks/pre-commit

# Run linting
npm run lint || exit 1

# Run tests
npm test || exit 1

# Check for secrets
if git diff --cached | grep -E '(password|api_key|secret)'; then
    echo "Possible secret detected. Commit aborted."
    exit 1
fi

预推送钩子

#!/bin/bash
# .git/hooks/pre-push

# Run full test suite
npm run test:all || exit 1

# Check for console.log statements
if git diff origin/main | grep -E 'console\.log'; then
    echo "Remove console.log statements before pushing."
    exit 1
fi

反模式

# BAD: Committing directly to main
git checkout main
git commit -m "fix bug"

# GOOD: Use feature branches and PRs

# BAD: Committing secrets
git add .env  # Contains API keys

# GOOD: Add to .gitignore, use environment variables

# BAD: Giant PRs (1000+ lines)
# GOOD: Break into smaller, focused PRs

# BAD: "Update" commit messages
git commit -m "update"
git commit -m "fix"

# GOOD: Descriptive messages
git commit -m "fix(auth): resolve redirect loop after login"

# BAD: Rewriting public history
git push --force origin main

# GOOD: Use revert for public branches
git revert HEAD

# BAD: Long-lived feature branches (weeks/months)
# GOOD: Keep branches short (days), rebase frequently

# BAD: Committing generated files
git add dist/
git add node_modules/

# GOOD: Add to .gitignore

快速参考

任务 命令
创建分支 git checkout -b feature/name
切换分支 git checkout branch-name
删除分支 git branch -d branch-name
合并分支 git merge branch-name
变基分支 git rebase main
查看历史 git log --oneline --graph
查看更改 git diff
暂存更改 git add . 或 git add -p
提交 git commit -m "message"
推送 git push origin branch-name
拉取 git pull origin branch-name
暂存工作区 git stash push -m "message"
撤销上次提交 git reset --soft HEAD~1
回滚提交 git revert HEAD

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC