Files
opencode/skill/git/SKILL.md

573 lines
13 KiB
Markdown

---
name: git
description: Git workflow best practices with commit conventions, tagging, and common operations for both polyrepo and monorepo
---
# Git Workflow Best Practices
You are an expert in Git version control and repository management.
## 功能文档
| 文档 | 说明 |
|------|------|
| [Commit Workflow](./commit-workflow.md) | 提交暂存文件,自动生成提交信息并创建版本标签 |
| [Push Workflow](./push-workflow.md) | 提交并推送到远程仓库的完整工作流 |
## Core Principles
1. **Default Main Branch**: Use `main` as the primary branch (not `master`)
2. **Conventional Commits**: Follow [Conventional Commits](https://www.conventionalcommits.org/) specification
3. **Semantic Versioning**: Use `major.minor.patch` format (e.g., `0.1.0`, `1.2.3`)
4. **Repository Types**: Support both polyrepo and monorepo workflows
5. **Clean History**: Maintain meaningful commit history and proper tagging
## Repository Types
### Polyrepo (Single Repository)
- Each project has its own repository
- Tag format: `<version>` (e.g., `1.2.0`)
- Version files at project root
- Simpler workflow for independent projects
### Monorepo (Multiple Subprojects)
- Multiple projects in a single repository
- Detect from `AGENTS.md` file or directory structure (e.g., `packages/`, `apps/`)
- Tag format: `<subproject>-<version>` (e.g., `ios-1.2.0`, `android-0.3.1`)
- Commit scope includes subproject name when changes affect single project
- Each subproject maintains independent versioning
**Monorepo Detection Rules:**
- Check if `AGENTS.md` explicitly indicates monorepo
- Look for common monorepo directory structures:
- `packages/`, `apps/`, `services/`, `modules/`, `projects/`
- If uncertain, default to polyrepo
## Commit Message Convention
### Format
```
<type>(<scope>): <subject>
<body>
<footer>
```
### Commit Types
| Type | Description | Version Impact | Examples |
|------|-------------|----------------|----------|
| `feat` | New feature | minor +1 | Add user authentication |
| `fix` | Bug fix | patch +1 | Fix memory leak in cache |
| `perf` | Performance improvement | patch +1 | Optimize database queries |
| `BREAKING CHANGE` or `!` | Breaking change | major +1 | Remove deprecated API |
| `docs` | Documentation only | None | Update README |
| `style` | Code style/formatting | None | Fix indentation |
| `refactor` | Code refactoring | None | Reorganize file structure |
| `test` | Add/modify tests | None | Add unit tests for auth |
| `chore` | Maintenance tasks | None | Update dependencies |
| `ci` | CI/CD changes | None | Update workflow config |
| `build` | Build system changes | None | Update webpack config |
### Commit Message Language
- **Default (macOS/Linux)**: Use Chinese (中文)
- **Windows**: Use English (due to Cursor Shell tool encoding issues)
- **Content**: Focus on "why" rather than "what"
- **Length**: Subject line ≤ 50 characters, body line ≤ 72 characters
### Scope (for Monorepo)
When changes affect a single subproject, include scope:
- Format: `<type>(<scope>): <subject>`
- Example: `feat(ios): add OGG Opus upload support`
- Example: `fix(electron): resolve clipboard injection issue`
When changes affect multiple subprojects or the entire repository, omit scope:
- Example: `chore: update shared dependencies`
### Examples
**Polyrepo commits:**
```bash
feat: add user authentication with OAuth2
fix: resolve bluetooth connection timeout
docs: update API documentation
chore: update project dependencies
```
**Monorepo commits:**
```bash
feat(ios): add OGG Opus upload support
fix(android): resolve memory leak in cache manager
refactor(electron): reorganize main process code
chore: update shared ESLint configuration
```
## Version Management
### Semantic Versioning
Format: `major.minor.patch` (e.g., `0.1.0`, `1.2.3`, `2.0.0`)
- **Default starting version**: `0.1.0`
- **Major** (X.0.0): Breaking changes, API incompatibility
- **Minor** (0.X.0): New features, backward compatible
- **Patch** (0.0.X): Bug fixes, backward compatible
### Version Increment Rules
| Change Type | Version Change | Example |
|-------------|----------------|---------|
| Breaking change | major +1, reset minor/patch | `1.2.3``2.0.0` |
| New feature (`feat`) | minor +1, reset patch | `1.2.3``1.3.0` |
| Bug fix (`fix`) | patch +1 | `1.2.3``1.2.4` |
| Performance (`perf`) | patch +1 | `1.2.3``1.2.4` |
### When to Update Version
**Update version** (user-perceivable changes):
- New features (`feat`)
- Bug fixes that affect users (`fix`)
- Performance improvements users can notice (`perf`)
- Breaking changes (major version bump)
**Don't update version** (internal changes):
- Documentation (`docs`)
- Tests (`test`)
- Refactoring without behavior change (`refactor`)
- Code style (`style`)
- Build configuration (`build`)
- CI/CD changes (`ci`)
- Maintenance tasks (`chore`)
**Decision criteria:**
1. Will this be packaged into the final product?
2. Will users notice this change?
3. Does it affect the product that users download/use?
If answer is "yes" → update version. Otherwise → skip version update.
## Project Type Detection
### Common Project Types
| Project Type | Version File | Version Field |
|--------------|--------------|---------------|
| iOS | `*.xcodeproj/project.pbxproj` | `MARKETING_VERSION` |
| npm/Node.js | `package.json` | `version` |
| Android (Groovy) | `app/build.gradle` | `versionName` |
| Android (Kotlin DSL) | `app/build.gradle.kts` | `versionName` |
| Python (pyproject) | `pyproject.toml` | `[project] version` or `[tool.poetry] version` |
| Python (setup) | `setup.py` | `version` |
| Rust | `Cargo.toml` | `[package] version` |
| Go | Git tag only | - |
| Flutter | `pubspec.yaml` | `version` |
| .NET | `*.csproj` | `<Version>` or `<PackageVersion>` |
### Detection Strategy
1. **Check AGENTS.md first**: If version rules are defined, use them
2. **Auto-detect**: Scan for version files based on project structure
3. **Fallback**: If no version file found, only create Git tag (like Go projects)
## Tag Management
### Tag Format
**Polyrepo:**
```bash
<version>
Examples: 1.2.0, 0.3.1, 2.0.0
```
**Monorepo:**
```bash
<subproject>-<version>
Examples: ios-1.2.0, android-0.3.1, electron-2.0.0
```
### Tag Annotation
- **Use same content as commit message** for tag annotation
- Tag annotations are used as Release notes by CI/CD
- Multi-line commits should have multi-line annotations
**Single-line example:**
```bash
git tag -a "1.2.0" -m "feat: add user authentication"
```
**Multi-line example (recommended):**
```bash
git tag -a "1.2.1" \
-m "fix: resolve bluetooth connection timeout" \
-m "" \
-m "- Increase connection timeout to 30s" \
-m "- Add retry mechanism for failed connections" \
-m "- Improve error messages"
```
**Monorepo example:**
```bash
git tag -a "android-1.2.1" \
-m "fix(android): resolve bluetooth connection timeout" \
-m "" \
-m "- Increase connection timeout to 30s" \
-m "- Add retry mechanism for failed connections"
```
### Tag Operations
**Create annotated tag:**
```bash
git tag -a "<tag-name>" -m "<message>"
```
**Push single tag:**
```bash
git push origin <tag-name>
```
**Push all tags:**
```bash
git push --tags
# or
git push origin --tags
```
**List recent tags:**
```bash
git tag --list | sort -V | tail -5
```
**Delete local tag:**
```bash
git tag -d <tag-name>
```
**Delete remote tag:**
```bash
git push origin --delete <tag-name>
# or
git push origin :refs/tags/<tag-name>
```
## Common Git Operations
### Check File Changes
**View changed files (working directory):**
```bash
git status
```
**View unstaged changes:**
```bash
git diff
```
**View staged changes:**
```bash
git diff --cached
# or
git diff --staged
```
**List changed files only:**
```bash
git diff --name-only
git diff --cached --name-only
```
**View specific file changes:**
```bash
git diff <file-path>
git diff --cached <file-path>
```
### Staging and Committing
**Add files to staging area:**
```bash
git add <file>
git add .
git add -A
```
**Check what's staged:**
```bash
git diff --cached --name-only
```
**Commit with message:**
```bash
# Single line
git commit -m "feat: add new feature"
# Multi-line (macOS/Linux)
git commit -m "$(cat <<'EOF'
feat: add new feature
- Detail 1
- Detail 2
EOF
)"
# Multi-line (Windows - use multiple -m flags)
git commit -m "feat: add new feature" -m "- Detail 1" -m "- Detail 2"
```
**Commit and tag in workflow:**
```bash
# 1. Check staging area
git diff --cached --name-only
# 2. Commit changes
git commit -m "feat: add user authentication"
# 3. Create tag
git tag -a "1.2.0" -m "feat: add user authentication"
# 4. Push both commit and tag
git push origin main
git push origin 1.2.0
```
### Pushing Changes
**Push current branch:**
```bash
git push origin $(git branch --show-current)
# or
git push origin main
```
**Push with upstream tracking:**
```bash
git push -u origin <branch-name>
```
**Push all tags:**
```bash
git push --tags
# or
git push origin --tags
```
**Push specific tag:**
```bash
git push origin <tag-name>
```
**Push commit and tag together:**
```bash
git push origin main && git push origin <tag-name>
```
### Branch Operations
**View current branch:**
```bash
git branch --show-current
```
**List all branches:**
```bash
git branch -a
```
**Create new branch:**
```bash
git branch <branch-name>
git checkout -b <branch-name>
# or (modern)
git switch -c <branch-name>
```
**Switch branch:**
```bash
git checkout <branch-name>
# or (modern)
git switch <branch-name>
```
**Delete branch:**
```bash
git branch -d <branch-name>
git branch -D <branch-name> # force delete
```
### History and Logs
**View commit history:**
```bash
git log --oneline -10
git log --graph --oneline --all
```
**View recent tags:**
```bash
git tag --list | sort -V | tail -5
```
**View commit details:**
```bash
git show <commit-hash>
git show <tag-name>
```
**Search commit history:**
```bash
git log --grep="<pattern>"
git log --author="<name>"
```
## Workflow Best Practices
### Standard Commit Workflow
1. **Check staging area:**
```bash
git diff --cached --name-only
```
- If empty, add files first: `git add .`
2. **Collect information (in parallel):**
```bash
git status
git diff --cached
git log --oneline -10
git tag --list | sort -V | tail -5
```
3. **Determine repository type:**
- Check `AGENTS.md` for monorepo indicator
- Analyze changed file paths for subproject scope
4. **Auto-detect project type:**
- Read `AGENTS.md` for version rules
- Scan for version files (package.json, build.gradle, etc.)
- Determine if version update is needed
5. **Generate commit message:**
- Analyze changes
- Follow Conventional Commits format
- Include scope for monorepo single-project changes
6. **Update version number (if needed):**
- Calculate new version based on change type
- Update version file
- Add version file to staging: `git add <version-file>`
- Verify: `git diff --cached --name-only`
7. **Commit changes:**
```bash
git commit -m "<message>"
```
8. **Create tag (if version updated):**
```bash
# Polyrepo
git tag -a "<version>" -m "<message>"
# Monorepo
git tag -a "<subproject>-<version>" -m "<message>"
```
9. **Push to remote:**
```bash
git push origin main
git push origin <tag-name> # if tag created
```
### Sync Configuration Workflow
**Pull latest config changes:**
```bash
cd ~/.config/opencode
git status # check for local changes
git pull origin main
git log --oneline -5 # view updates
```
**Push config changes:**
```bash
cd ~/.config/opencode
git status # check changes
git add command/ skill/ opencode.json
git commit -m "feat: add new git skill"
git push origin main
```
## Platform-Specific Considerations
### macOS/Linux
- **Commit language**: Use Chinese (中文)
- **Multi-line commits**: Use heredoc with `cat <<'EOF'`
- **Encoding**: UTF-8 without BOM (default)
### Windows
- **Commit language**: Use English only (Cursor Shell encoding issue)
- **Multi-line commits**: Use multiple `-m` flags
- **Prohibited methods**:
- No Chinese commit messages
- No `Out-File -Encoding utf8` (adds BOM)
- No PowerShell here-strings `@"..."@`
- No Write tool for temp files (encoding issues)
## Error Prevention
1. **Always check staging area first**: Don't commit empty staging area
2. **Verify version file is staged**: After updating version, confirm with `git diff --cached --name-only`
3. **No --amend after push**: Never amend commits that are already pushed
4. **Tag naming conflicts**: Check existing tags before creating new ones
5. **Branch protection**: Never force push to main/master without explicit user request
6. **Sensitive data**: Never commit secrets, API keys, or credentials
## Integration with CI/CD
- **Tag annotations**: Used as Release notes
- **Version consistency**: Git tag must match version file
- **Automated releases**: Tags trigger CI/CD pipelines
- **Semantic versioning**: CI/CD determines release type from version bump
## Quick Reference
**Check status:**
```bash
git status
git diff --cached --name-only
```
**Commit with tag:**
```bash
git commit -m "feat: add feature"
git tag -a "1.2.0" -m "feat: add feature"
git push origin main && git push origin 1.2.0
```
**Push all tags:**
```bash
git push --tags
```
**View recent history:**
```bash
git log --oneline -10
git tag --list | sort -V | tail -5
```
**View changes:**
```bash
git diff # unstaged changes
git diff --cached # staged changes
git diff main..feature # compare branches
```