Back to skills
SkillHub ClubRun DevOpsFull StackDevOps

git-workflow

Agent Skill: Git workflow best practices for teams and CI/CD. Use when establishing branching strategies, implementing Conventional Commits, configuring PRs, or integrating Git with CI/CD. By Netresearch.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
22
Hot score
88
Updated
March 19, 2026
Overall rating
C3.6
Composite score
3.6
Best-practice grade
B70.0

Install command

npx @skill-hub/cli install netresearch-claude-code-marketplace-git-workflow

Repository

netresearch/claude-code-marketplace

Skill path: skills/git-workflow/skills/git-workflow

Agent Skill: Git workflow best practices for teams and CI/CD. Use when establishing branching strategies, implementing Conventional Commits, configuring PRs, or integrating Git with CI/CD. By Netresearch.

Open repository

Best for

Primary workflow: Run DevOps.

Technical facets: Full Stack, DevOps.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: netresearch.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install git-workflow into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/netresearch/claude-code-marketplace before adding git-workflow to shared team environments
  • Use git-workflow for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: git-workflow
description: "Agent Skill: Git workflow best practices for teams and CI/CD. Use when establishing branching strategies, implementing Conventional Commits, configuring PRs, or integrating Git with CI/CD. By Netresearch."
---

# Git Workflow Skill

Expert patterns for Git version control: branching, commits, collaboration, and CI/CD.

## Expertise Areas

- **Branching**: Git Flow, GitHub Flow, Trunk-based development
- **Commits**: Conventional Commits, semantic versioning
- **Collaboration**: PR workflows, code review, merge strategies
- **CI/CD**: GitHub Actions, GitLab CI, branch protection

## Reference Files

Detailed documentation for each area:

- `references/branching-strategies.md` - Branch management patterns
- `references/commit-conventions.md` - Commit message standards
- `references/pull-request-workflow.md` - PR and review processes
- `references/ci-cd-integration.md` - Automation patterns
- `references/advanced-git.md` - Advanced Git operations
- `references/github-releases.md` - Release management, immutable releases

## Conventional Commits (Quick Reference)

```
<type>[scope]: <description>
```

**Types**: `feat` (MINOR), `fix` (PATCH), `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`

**Breaking change**: Add `!` after type or `BREAKING CHANGE:` in footer.

## Branch Naming

```bash
feature/TICKET-123-description
fix/TICKET-456-bug-name
release/1.2.0
hotfix/1.2.1-security-patch
```

## GitHub Flow (Default)

```bash
git checkout main && git pull
git checkout -b feature/my-feature
# ... work ...
git push -u origin HEAD
gh pr create && gh pr merge --squash
```

## Verification

```bash
./scripts/verify-git-workflow.sh /path/to/repository
```

## GitHub Immutable Releases

**CRITICAL**: Deleted releases block tag names PERMANENTLY. Get releases right first time.

See `references/github-releases.md` for prevention and recovery patterns.

---

> **Contributing:** https://github.com/netresearch/git-workflow-skill


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/branching-strategies.md

```markdown
# Git Branching Strategies

## Git Flow

### Overview

Git Flow is a branching model designed for projects with scheduled releases.

```
main ─────●─────────────────●─────────────────●─────── (production)
          │                 │                 │
          │    release/1.0  │    release/1.1  │
          │    ┌───●───●────┤    ┌───●───●────┤
          │    │            │    │            │
develop ──●────●────●───●───●────●────●───●───●─────── (integration)
               │    │        │    │    │
               │    │        │    │    └── feature/C
               │    └────────┴────┴─────── feature/B
               └─────────────────────────── feature/A
```

### Branch Types

| Branch | Purpose | Created From | Merges To |
|--------|---------|--------------|-----------|
| `main` | Production code | - | - |
| `develop` | Integration | `main` | `release` |
| `feature/*` | New features | `develop` | `develop` |
| `release/*` | Release prep | `develop` | `main`, `develop` |
| `hotfix/*` | Emergency fixes | `main` | `main`, `develop` |

### Commands

```bash
# Initialize
git flow init

# Feature
git flow feature start user-auth
git flow feature publish user-auth    # Push to remote
git flow feature finish user-auth

# Release
git flow release start 1.2.0
git flow release publish 1.2.0
git flow release finish 1.2.0

# Hotfix
git flow hotfix start 1.2.1
git flow hotfix finish 1.2.1
```

### When to Use

**Good for:**
- Scheduled release cycles
- Long-lived feature branches
- Multiple versions in production
- Teams with dedicated release managers

**Avoid when:**
- Continuous deployment
- Small teams
- Rapid iteration needed

## GitHub Flow

### Overview

Simplified workflow ideal for continuous deployment.

```
main ───●───●───────────●───────●───●─── (always deployable)
        │   │           │       │   │
        │   └── PR #2 ──┘       │   └── PR #4
        │                       │
        └───── PR #1 ───────────┴─────── PR #3
```

### Rules

1. `main` is always deployable
2. Create descriptive feature branches from `main`
3. Push commits regularly
4. Open PR for discussion/review
5. Merge after review and CI passes
6. Deploy immediately after merge

### Workflow

```bash
# 1. Start feature
git checkout main
git pull origin main
git checkout -b add-user-notifications

# 2. Develop with regular commits
git add .
git commit -m "feat: add notification service"
git push -u origin add-user-notifications

# 3. Create PR
gh pr create --title "Add user notifications" \
  --body "Implements email and push notifications for users"

# 4. Address review feedback
git add .
git commit -m "fix: address review comments"
git push

# 5. Merge (after approval and CI)
gh pr merge --squash --delete-branch

# 6. Deploy (automatic via CI/CD)
```

### When to Use

**Good for:**
- Continuous deployment
- Web applications
- Small to medium teams
- Fast iteration cycles

**Avoid when:**
- Multiple versions in production
- Scheduled releases required

## Trunk-Based Development

### Overview

All developers work on a single branch with short-lived feature branches.

```
main ───●───●───●───●───●───●───●───●───●───●─── (trunk)
        │   │       │       │   │       │
        └─┬─┘       └───┬───┘   └───┬───┘
          │             │           │
        small         small       small
        feature       feature     feature
        (< 1 day)     (< 1 day)   (< 1 day)
```

### Principles

1. **Single branch**: All code goes to `main`/`trunk`
2. **Short-lived branches**: Max 1-2 days
3. **Feature flags**: Hide incomplete features
4. **Continuous integration**: Merge multiple times per day
5. **No long-running branches**: Avoid merge conflicts

### Workflow

```bash
# Start small feature (should complete today)
git checkout main
git pull
git checkout -b small-feature

# Work in small increments
git add .
git commit -m "feat: add basic structure"
git push

# Merge quickly (within hours/day)
gh pr create --title "Small feature"
gh pr merge --rebase

# Feature flags for incomplete work
if (featureFlags.isEnabled('new-checkout')) {
    // New checkout flow
} else {
    // Existing checkout flow
}
```

### Release Strategies

```bash
# Option 1: Release from trunk
git tag v1.2.0
git push origin v1.2.0

# Option 2: Release branches (for fixes)
git checkout -b release/1.2 main
# Cherry-pick fixes if needed
git cherry-pick <fix-commit>
git tag v1.2.1
```

### When to Use

**Good for:**
- Mature CI/CD pipelines
- High test coverage
- Experienced teams
- Microservices

**Avoid when:**
- Junior-heavy teams
- Low test coverage
- Multiple long-term versions

## GitLab Flow

### Overview

Combines feature branches with environment branches.

```
main ─────●─────●─────●─────●─────●───── (development)
          │     │     │     │     │
          ▼     ▼     ▼     ▼     ▼
staging ──●─────●─────●─────●─────●───── (staging env)
                │           │     │
                ▼           ▼     ▼
production ─────●───────────●─────●───── (production env)
```

### Environment Branches

```bash
# Feature development
git checkout -b feature/new-api main
# ... develop ...
git checkout main
git merge feature/new-api

# Promote to staging
git checkout staging
git merge main

# Promote to production (after staging verification)
git checkout production
git merge staging
git tag v1.2.0
```

### With Release Branches

```bash
# Support multiple versions
main
├── release/1.x
│   ├── 1.0.0
│   ├── 1.0.1
│   └── 1.1.0
└── release/2.x
    ├── 2.0.0
    └── 2.0.1
```

## Choosing a Strategy

### Decision Matrix

| Factor | Git Flow | GitHub Flow | Trunk-Based | GitLab Flow |
|--------|----------|-------------|-------------|-------------|
| Release frequency | Scheduled | Continuous | Continuous | Environment-based |
| Team size | Large | Small-Medium | Any | Any |
| Version support | Multiple | Single | Single | Multiple |
| Branch complexity | High | Low | Very Low | Medium |
| CI/CD maturity | Any | Medium | High | Medium |
| Merge conflicts | More | Less | Least | Medium |

### Quick Guide

```
Need scheduled releases?
├── Yes → Multiple versions in production?
│         ├── Yes → Git Flow
│         └── No  → GitLab Flow (with releases)
└── No  → Continuous deployment ready?
          ├── Yes → High test coverage?
          │         ├── Yes → Trunk-Based
          │         └── No  → GitHub Flow
          └── No  → GitHub Flow
```

## Branch Protection

### GitHub Branch Protection Rules

```yaml
# Settings > Branches > Branch protection rules
main:
  require_pull_request:
    required_approving_reviews: 2
    dismiss_stale_reviews: true
    require_code_owner_reviews: true
  require_status_checks:
    strict: true
    contexts:
      - "ci/lint"
      - "ci/test"
      - "ci/build"
  require_conversation_resolution: true
  require_signed_commits: false
  include_administrators: true
  allow_force_pushes: false
  allow_deletions: false
```

### GitLab Protected Branches

```yaml
# Settings > Repository > Protected branches
main:
  allowed_to_push:
    - role: maintainer
  allowed_to_merge:
    - role: developer
  allowed_to_force_push: false
  code_owner_approval_required: true
```

## Migration Between Strategies

### Git Flow → GitHub Flow

```bash
# 1. Merge develop to main
git checkout main
git merge develop

# 2. Delete develop branch
git branch -d develop
git push origin --delete develop

# 3. Update CI/CD to deploy from main
# 4. Communicate new workflow to team
# 5. Update branch protection rules
```

### GitHub Flow → Trunk-Based

```bash
# 1. Implement feature flags
# 2. Increase test coverage
# 3. Set up continuous deployment
# 4. Shorten PR review cycle
# 5. Enforce small, frequent merges
```

```

### references/commit-conventions.md

```markdown
# Commit Conventions

## Conventional Commits

### Specification

```
<type>[optional scope]: <description>

[optional body]

[optional footer(s)]
```

### Commit Types

| Type | Description | Version Bump |
|------|-------------|--------------|
| `feat` | New feature | MINOR |
| `fix` | Bug fix | PATCH |
| `docs` | Documentation only | - |
| `style` | Code style (formatting) | - |
| `refactor` | Code refactoring | - |
| `perf` | Performance improvement | PATCH |
| `test` | Adding/updating tests | - |
| `build` | Build system changes | - |
| `ci` | CI configuration | - |
| `chore` | Maintenance tasks | - |
| `revert` | Reverting changes | - |

### Examples

```bash
# Simple feature
feat: add user authentication

# Feature with scope
feat(auth): add OAuth2 login support

# Bug fix
fix: resolve null pointer in user service

# Bug fix with issue reference
fix(api): handle empty response from external service

Fixes #123

# Breaking change
feat!: remove deprecated v1 API endpoints

BREAKING CHANGE: The /api/v1/* endpoints have been removed.
Migrate to /api/v2/* before upgrading.

# Multiple footers
fix(security): patch XSS vulnerability in comment parser

Reviewed-by: John Doe
Refs: #456
```

### Scope Guidelines

Scopes should be consistent across the project:

```bash
# By feature area
feat(auth): ...
feat(payment): ...
feat(notification): ...

# By layer
fix(api): ...
fix(db): ...
fix(ui): ...

# By component
style(button): ...
refactor(modal): ...
```

## Commit Message Best Practices

### Subject Line

```bash
# ✅ Good: Imperative mood, present tense
feat: add password reset functionality
fix: prevent duplicate form submissions

# ❌ Bad: Past tense, not imperative
feat: added password reset functionality
fix: fixed duplicate form submissions

# ✅ Good: Specific and concise
feat: implement rate limiting for API endpoints

# ❌ Bad: Vague
feat: improve API

# ✅ Good: Under 72 characters
fix: resolve race condition in cache invalidation

# ❌ Bad: Too long
fix: resolve the race condition that was occurring in the cache invalidation process when multiple users were accessing the same resource simultaneously
```

### Body

```bash
# When to include a body:
# - Complex changes needing explanation
# - Non-obvious implementation choices
# - Context for future readers

fix: prevent race condition in order processing

The previous implementation allowed concurrent modifications to the
same order, leading to inconsistent state.

This change introduces optimistic locking using version numbers.
When a conflict is detected, the operation is retried with fresh data.

The retry limit is set to 3 attempts to prevent infinite loops.
```

### Footer

```bash
# Issue references
fix: resolve login timeout

Fixes #123
Closes #456

# Breaking changes
feat!: update authentication API

BREAKING CHANGE: The `authenticate()` method now returns a Promise
instead of using callbacks. Update all call sites to use async/await.

# Co-authors
feat: implement new dashboard

Co-authored-by: Jane Doe <[email protected]>
Co-authored-by: John Smith <[email protected]>

# Review references
fix: patch security vulnerability

Reviewed-by: Security Team
Approved-by: @security-lead
```

## Atomic Commits

### Principles

1. **One logical change per commit**
2. **Each commit should compile/pass tests**
3. **Related changes grouped together**
4. **Unrelated changes in separate commits**

### Examples

```bash
# ❌ Bad: Multiple unrelated changes
git add .
git commit -m "feat: add login page and fix typo in readme and update deps"

# ✅ Good: Separate commits
git add src/pages/Login.tsx src/components/LoginForm.tsx
git commit -m "feat(auth): add login page with form validation"

git add README.md
git commit -m "docs: fix typo in installation instructions"

git add package.json package-lock.json
git commit -m "build: update dependencies to latest versions"
```

### Interactive Staging

```bash
# Stage specific hunks
git add -p

# Options:
# y - stage this hunk
# n - skip this hunk
# s - split into smaller hunks
# e - manually edit hunk
# q - quit

# Stage specific files
git add src/feature/
git commit -m "feat: add feature files"

git add tests/feature/
git commit -m "test: add tests for feature"
```

## Commit Templates

### Setup

```bash
# Create template file
cat > ~/.gitmessage << 'EOF'
# <type>(<scope>): <subject>
# |<----  Using a Maximum Of 50 Characters  ---->|

# Explain why this change is being made
# |<----   Try To Limit Each Line to a Maximum Of 72 Characters   ---->|

# Provide links or keys to any relevant tickets, articles or other resources
# Example: Fixes #23

# --- COMMIT END ---
# Type can be:
#   feat     (new feature)
#   fix      (bug fix)
#   docs     (changes to documentation)
#   style    (formatting, missing semi colons, etc; no code change)
#   refactor (refactoring production code)
#   test     (adding missing tests, refactoring tests; no production code change)
#   chore    (updating grunt tasks etc; no production code change)
#   perf     (performance improvements)
#   ci       (CI configuration)
#   build    (build system changes)
# --------------------
EOF

# Configure git to use template
git config --global commit.template ~/.gitmessage
```

### Project-Specific Template

```bash
# .gitmessage in project root
# <type>(<scope>): <subject>

# Body: Explain the motivation for the change

# Footer:
# Fixes #issue
# BREAKING CHANGE: description

# ---
# Remember:
# - Use present tense ("add" not "added")
# - Use imperative mood ("move" not "moves")
# - First line max 50 chars, body wrap at 72
# - Reference issues and PRs at the bottom
```

## Commit Message Validation

### Git Hook (commit-msg)

```bash
#!/bin/bash
# .git/hooks/commit-msg

commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")

# Skip merge commits
if echo "$commit_msg" | grep -qE "^Merge"; then
    exit 0
fi

# Conventional commit pattern
pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9-]+\))?(!)?: .{1,50}"

if ! echo "$commit_msg" | head -1 | grep -qE "$pattern"; then
    echo "ERROR: Invalid commit message format"
    echo ""
    echo "Expected: <type>(<scope>): <subject>"
    echo "  type:    feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert"
    echo "  scope:   optional, lowercase with hyphens"
    echo "  subject: max 50 chars, imperative mood"
    echo ""
    echo "Your message:"
    echo "  $(head -1 "$commit_msg_file")"
    exit 1
fi

# Check subject line length
subject=$(echo "$commit_msg" | head -1)
if [ ${#subject} -gt 72 ]; then
    echo "ERROR: Subject line too long (${#subject} > 72 chars)"
    exit 1
fi

# Check for trailing period
if echo "$subject" | grep -qE "\.$"; then
    echo "ERROR: Subject line should not end with a period"
    exit 1
fi

exit 0
```

### commitlint Configuration

```javascript
// commitlint.config.js
module.exports = {
    extends: ['@commitlint/config-conventional'],
    rules: {
        'type-enum': [2, 'always', [
            'feat', 'fix', 'docs', 'style', 'refactor',
            'perf', 'test', 'build', 'ci', 'chore', 'revert'
        ]],
        'scope-case': [2, 'always', 'kebab-case'],
        'subject-case': [2, 'always', 'lower-case'],
        'subject-max-length': [2, 'always', 72],
        'body-max-line-length': [2, 'always', 100],
    },
};
```

```json
// package.json
{
    "husky": {
        "hooks": {
            "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
        }
    }
}
```

## Semantic Release Integration

### Configuration

```json
// .releaserc
{
    "branches": ["main"],
    "plugins": [
        ["@semantic-release/commit-analyzer", {
            "preset": "conventionalcommits",
            "releaseRules": [
                {"type": "feat", "release": "minor"},
                {"type": "fix", "release": "patch"},
                {"type": "perf", "release": "patch"},
                {"type": "revert", "release": "patch"},
                {"breaking": true, "release": "major"}
            ]
        }],
        ["@semantic-release/release-notes-generator", {
            "preset": "conventionalcommits"
        }],
        "@semantic-release/changelog",
        "@semantic-release/npm",
        "@semantic-release/github"
    ]
}
```

### Version Bumping

```bash
# These commits determine version bumps:

# PATCH (1.0.x)
fix: correct typo in error message
perf: optimize database query

# MINOR (1.x.0)
feat: add user profile page
feat(api): implement caching layer

# MAJOR (x.0.0)
feat!: redesign authentication system
fix!: change API response format

BREAKING CHANGE: Response format changed from XML to JSON
```

## Rewriting History

### Amending Commits

```bash
# Fix last commit message
git commit --amend -m "feat: correct commit message"

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

# Change author
git commit --amend --author="Name <[email protected]>"
```

### Interactive Rebase

```bash
# Rewrite last 5 commits
git rebase -i HEAD~5

# Commands in editor:
# pick   - use commit
# reword - edit message
# edit   - stop and amend
# squash - combine with previous
# fixup  - combine, discard message
# drop   - remove commit

# Example: Squash fixup commits
pick abc1234 feat: add user API
fixup def5678 fixup! feat: add user API
pick ghi9012 feat: add admin API
```

### Fixup Commits

```bash
# Create fixup commit
git add .
git commit --fixup=abc1234

# Auto-squash during rebase
git rebase -i --autosquash main
```

## Best Practices Summary

1. **Write meaningful messages**: Future you will thank present you
2. **Use conventional commits**: Enable automated versioning
3. **Keep commits atomic**: One logical change per commit
4. **Reference issues**: Link commits to project management
5. **Use scopes consistently**: Help with changelog generation
6. **Don't include generated files**: Keep commits focused on source changes
7. **Sign commits** (optional): Verify authorship with GPG

```

### references/pull-request-workflow.md

```markdown
# Pull Request Workflow

## PR Best Practices

### Size Guidelines

| Size | Lines Changed | Review Time | Defect Risk |
|------|--------------|-------------|-------------|
| XS | 0-10 | < 5 min | Very Low |
| S | 11-100 | 15-30 min | Low |
| M | 101-400 | 30-60 min | Medium |
| L | 401-1000 | 1-2 hours | High |
| XL | 1000+ | Multiple sessions | Very High |

**Target**: Keep PRs under 400 lines when possible.

### PR Structure

```markdown
## Summary
Brief description of changes and motivation.

## Type of Change
- [ ] Bug fix (non-breaking change fixing an issue)
- [ ] New feature (non-breaking change adding functionality)
- [ ] Breaking change (fix or feature causing existing functionality to change)
- [ ] Documentation update
- [ ] Refactoring (no functional changes)

## Changes Made
- Added user authentication service
- Implemented JWT token generation
- Added login/logout endpoints

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

## Screenshots (if applicable)
[Before/After screenshots for UI changes]

## Related Issues
Fixes #123
Related to #456

## Checklist
- [ ] Code follows project style guidelines
- [ ] Self-review performed
- [ ] Documentation updated
- [ ] No new warnings introduced
- [ ] Tests pass locally
```

## Creating PRs

### GitHub CLI

```bash
# Create PR with title and body
gh pr create \
  --title "feat(auth): add user authentication" \
  --body "## Summary
Implements JWT-based authentication.

## Changes
- Add AuthService
- Add login/logout endpoints
- Add auth middleware

Fixes #123"

# Create draft PR
gh pr create --draft

# Create PR and assign reviewers
gh pr create \
  --title "fix: resolve memory leak" \
  --reviewer "@team-lead,@senior-dev" \
  --assignee "@me"

# Create PR from template
gh pr create --template .github/PULL_REQUEST_TEMPLATE.md
```

### PR Templates

```markdown
<!-- .github/PULL_REQUEST_TEMPLATE.md -->
## Description
<!-- Describe your changes in detail -->

## Motivation and Context
<!-- Why is this change required? What problem does it solve? -->

## How Has This Been Tested?
<!-- Describe how you tested your changes -->

## Types of Changes
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation

## Checklist
- [ ] My code follows the code style of this project
- [ ] I have updated the documentation accordingly
- [ ] I have added tests to cover my changes
- [ ] All new and existing tests passed
```

### Multiple Templates

```
.github/
├── PULL_REQUEST_TEMPLATE.md          # Default
└── PULL_REQUEST_TEMPLATE/
    ├── feature.md
    ├── bugfix.md
    └── documentation.md
```

## Code Review Process

### Reviewer Responsibilities

1. **Code Quality**
   - Readability and maintainability
   - Adherence to coding standards
   - Appropriate error handling

2. **Functionality**
   - Logic correctness
   - Edge cases handled
   - Requirements met

3. **Testing**
   - Test coverage adequate
   - Tests meaningful and correct
   - Edge cases tested

4. **Security**
   - No obvious vulnerabilities
   - Sensitive data handling
   - Input validation

5. **Performance**
   - No obvious bottlenecks
   - Resource usage appropriate
   - Scaling considerations

### Review Comments

```markdown
# Levels of feedback

# 🔴 Blocking - Must be addressed
This introduces a security vulnerability. User input is not sanitized
before being used in the SQL query.

# 🟡 Suggestion - Should consider
Consider extracting this logic into a separate function for reusability
and testing.

# 🟢 Nit - Minor issue
Nit: This variable name could be more descriptive.
`data` → `userProfileData`

# 💡 Question - Seeking understanding
Question: What's the reasoning behind using a Map here instead of an Object?

# 👍 Praise - Positive feedback
Nice catch handling the edge case where the array might be empty!
```

### Review Checklist

```markdown
## Code Review Checklist

### Code Quality
- [ ] Code is readable and self-documenting
- [ ] No unnecessary complexity
- [ ] DRY principle followed
- [ ] SOLID principles followed

### Testing
- [ ] Unit tests present and passing
- [ ] Edge cases covered
- [ ] Integration tests if needed
- [ ] No flaky tests introduced

### Security
- [ ] No hardcoded credentials
- [ ] Input validation present
- [ ] No SQL injection risks
- [ ] No XSS vulnerabilities

### Performance
- [ ] No N+1 queries
- [ ] Appropriate data structures used
- [ ] No memory leaks
- [ ] Caching considered

### Documentation
- [ ] README updated if needed
- [ ] API documentation updated
- [ ] Comments for complex logic
- [ ] CHANGELOG entry added
```

## Merge Strategies

### Merge Commit

```bash
# Creates a merge commit, preserves all history
git checkout main
git merge --no-ff feature/my-feature

# Result:
#   * Merge branch 'feature/my-feature'
#   |\
#   | * feat: add feature part 2
#   | * feat: add feature part 1
#   |/
#   * Previous main commit
```

**Use when:**
- Want to preserve complete branch history
- Complex features with meaningful intermediate commits
- Audit trail required

### Squash and Merge

```bash
# Combines all commits into one
git checkout main
git merge --squash feature/my-feature
git commit -m "feat: complete feature implementation"

# Result:
#   * feat: complete feature implementation
#   * Previous main commit
```

**Use when:**
- Feature branch has messy history
- WIP commits, fixups, "oops" commits
- Want clean linear history

### Rebase and Merge

```bash
# Replays commits on top of main
git checkout feature/my-feature
git rebase main
git checkout main
git merge --ff-only feature/my-feature

# Result:
#   * feat: add feature part 2
#   * feat: add feature part 1
#   * Previous main commit
```

**Use when:**
- Clean commit history in feature branch
- Each commit is meaningful and tested
- Want linear history without merge commits

### Comparison

| Strategy | History | Complexity | Traceability |
|----------|---------|------------|--------------|
| Merge | Preserved | High | High |
| Squash | Combined | Low | Medium |
| Rebase | Linear | Low | Medium |

## Automated Checks

### GitHub Actions for PRs

```yaml
# .github/workflows/pr-checks.yml
name: PR Checks

on:
  pull_request:
    branches: [main, develop]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test -- --coverage

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run build

  pr-size:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Check PR size
        run: |
          ADDITIONS=$(gh pr view ${{ github.event.pull_request.number }} --json additions -q '.additions')
          if [ "$ADDITIONS" -gt 1000 ]; then
            echo "::warning::Large PR detected ($ADDITIONS lines). Consider splitting."
          fi
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

### Required Status Checks

```yaml
# Branch protection settings
required_status_checks:
  strict: true
  contexts:
    - lint
    - test
    - build
    - security-scan
```

### CODEOWNERS

```bash
# .github/CODEOWNERS

# Default owners for everything
* @default-team

# Frontend owners
/src/components/ @frontend-team
/src/styles/ @frontend-team @design-team

# Backend owners
/src/api/ @backend-team
/src/database/ @backend-team @dba-team

# DevOps owners
/.github/ @devops-team
/docker/ @devops-team
/terraform/ @devops-team

# Documentation
/docs/ @docs-team
*.md @docs-team

# Security-sensitive files
/src/auth/ @security-team @backend-team
/src/crypto/ @security-team
```

## PR Lifecycle

### States

```
Draft → Ready for Review → Changes Requested → Approved → Merged
         ↑_____________________|
```

### Commands

```bash
# Check PR status
gh pr status
gh pr view 123

# Request review
gh pr edit 123 --add-reviewer "@reviewer1,@reviewer2"

# Mark ready for review
gh pr ready 123

# Convert to draft
gh pr ready 123 --undo

# Approve PR
gh pr review 123 --approve

# Request changes
gh pr review 123 --request-changes --body "Please fix X"

# Merge PR
gh pr merge 123 --squash --delete-branch

# Close without merging
gh pr close 123
```

### Handling Stale PRs

```yaml
# .github/workflows/stale.yml
name: Mark Stale PRs

on:
  schedule:
    - cron: '0 0 * * *'  # Daily

jobs:
  stale:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v9
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          stale-pr-message: 'This PR has been inactive for 14 days. Please update or close.'
          days-before-stale: 14
          days-before-close: 7
          stale-pr-label: 'stale'
```

## Conflict Resolution

### Before Merging

```bash
# Update feature branch with latest main
git checkout feature/my-feature
git fetch origin
git rebase origin/main

# If conflicts occur
# 1. Edit conflicting files
# 2. Stage resolved files
git add <resolved-file>
# 3. Continue rebase
git rebase --continue

# Force push (only on feature branches!)
git push --force-with-lease
```

### Merge Conflicts in PR

```bash
# Option 1: Rebase (preferred for clean history)
git checkout feature/my-feature
git fetch origin
git rebase origin/main
# Resolve conflicts
git push --force-with-lease

# Option 2: Merge main into feature
git checkout feature/my-feature
git merge origin/main
# Resolve conflicts
git commit
git push
```

### Complex Conflicts

```bash
# Use a merge tool
git mergetool

# Or use specific tool
git mergetool --tool=vscode
git mergetool --tool=meld

# Configure default tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
```

## PR Analytics

### Metrics to Track

1. **PR Size**: Average lines changed
2. **Review Time**: Time from creation to first review
3. **Time to Merge**: Creation to merge
4. **Review Rounds**: Number of change requests
5. **Throughput**: PRs merged per week

### GitHub Insights

```bash
# List PR stats
gh pr list --state merged --json number,title,createdAt,mergedAt,additions,deletions

# PR age analysis
gh pr list --state open --json number,createdAt | jq 'map({number, age: (now - (.createdAt | fromdateiso8601)) / 86400})'
```

```

### references/ci-cd-integration.md

```markdown
# CI/CD Integration

## GitHub Actions

### Basic Workflow Structure

```yaml
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]
  workflow_dispatch:  # Manual trigger

env:
  NODE_VERSION: '20'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      - run: npm ci
      - run: npm run build
```

### Complete CI Pipeline

```yaml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    needs: lint
    strategy:
      matrix:
        node: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
          cache: 'npm'
      - run: npm ci
      - run: npm test -- --coverage
      - uses: codecov/codecov-action@v4
        if: matrix.node == 20

  build:
    runs-on: ubuntu-latest
    needs: test
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: build
          path: dist/

  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run security audit
        run: npm audit --audit-level=high
      - name: Run Snyk
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

  deploy-staging:
    runs-on: ubuntu-latest
    needs: [build, security]
    if: github.ref == 'refs/heads/develop'
    environment: staging
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: build
          path: dist/
      - name: Deploy to staging
        run: |
          # Deploy commands here

  deploy-production:
    runs-on: ubuntu-latest
    needs: [build, security]
    if: github.ref == 'refs/heads/main'
    environment: production
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: build
          path: dist/
      - name: Deploy to production
        run: |
          # Deploy commands here
```

### Reusable Workflows

```yaml
# .github/workflows/reusable-test.yml
name: Reusable Test Workflow

on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
    secrets:
      npm-token:
        required: false

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
      - run: npm test
```

```yaml
# .github/workflows/ci.yml
name: CI

on: [push, pull_request]

jobs:
  call-test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '20'
    secrets:
      npm-token: ${{ secrets.NPM_TOKEN }}
```

### Matrix Builds

```yaml
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node: [18, 20, 22]
        exclude:
          - os: windows-latest
            node: 18
      fail-fast: false
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test
```

## GitLab CI

### Basic Pipeline

```yaml
# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

variables:
  NODE_VERSION: "20"

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/

build:
  stage: build
  image: node:${NODE_VERSION}
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

test:
  stage: test
  image: node:${NODE_VERSION}
  script:
    - npm ci
    - npm test
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'

deploy_staging:
  stage: deploy
  script:
    - ./deploy.sh staging
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

deploy_production:
  stage: deploy
  script:
    - ./deploy.sh production
  environment:
    name: production
    url: https://example.com
  only:
    - main
  when: manual
```

### Multi-Stage Pipeline

```yaml
stages:
  - prepare
  - build
  - test
  - security
  - deploy

.node-base:
  image: node:20
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/

install:
  extends: .node-base
  stage: prepare
  script:
    - npm ci
  artifacts:
    paths:
      - node_modules/
    expire_in: 1 hour

lint:
  extends: .node-base
  stage: build
  needs: [install]
  script:
    - npm run lint

build:
  extends: .node-base
  stage: build
  needs: [install]
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 day

unit-test:
  extends: .node-base
  stage: test
  needs: [install]
  script:
    - npm run test:unit
  coverage: '/Statements\s*:\s*(\d+\.?\d*)%/'

integration-test:
  extends: .node-base
  stage: test
  needs: [build]
  services:
    - postgres:15
  variables:
    POSTGRES_DB: test
    POSTGRES_USER: test
    POSTGRES_PASSWORD: test
  script:
    - npm run test:integration

security-audit:
  stage: security
  needs: [install]
  script:
    - npm audit --audit-level=high
  allow_failure: true

sast:
  stage: security
  include:
    - template: Security/SAST.gitlab-ci.yml
```

## Semantic Release

### Configuration

```json
// .releaserc.json
{
  "branches": [
    "main",
    {"name": "beta", "prerelease": true},
    {"name": "alpha", "prerelease": true}
  ],
  "plugins": [
    ["@semantic-release/commit-analyzer", {
      "preset": "conventionalcommits",
      "releaseRules": [
        {"type": "feat", "release": "minor"},
        {"type": "fix", "release": "patch"},
        {"type": "perf", "release": "patch"},
        {"breaking": true, "release": "major"}
      ]
    }],
    ["@semantic-release/release-notes-generator", {
      "preset": "conventionalcommits",
      "presetConfig": {
        "types": [
          {"type": "feat", "section": "Features"},
          {"type": "fix", "section": "Bug Fixes"},
          {"type": "perf", "section": "Performance"},
          {"type": "revert", "section": "Reverts"}
        ]
      }
    }],
    ["@semantic-release/changelog", {
      "changelogFile": "CHANGELOG.md"
    }],
    ["@semantic-release/npm", {
      "npmPublish": true
    }],
    ["@semantic-release/git", {
      "assets": ["CHANGELOG.md", "package.json"],
      "message": "chore(release): ${nextRelease.version} [skip ci]"
    }],
    "@semantic-release/github"
  ]
}
```

### GitHub Actions Integration

```yaml
name: Release

on:
  push:
    branches: [main]

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          persist-credentials: false

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm ci

      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release
```

## Branch Protection

### GitHub Settings

```yaml
# Via GitHub API or settings UI
branch_protection:
  main:
    required_status_checks:
      strict: true
      contexts:
        - lint
        - test
        - build
        - security
    required_pull_request_reviews:
      required_approving_review_count: 2
      dismiss_stale_reviews: true
      require_code_owner_reviews: true
    restrictions:
      users: []
      teams: [core-team]
    enforce_admins: true
    require_linear_history: true
    allow_force_pushes: false
    allow_deletions: false
```

### GitLab Settings

```yaml
# Via GitLab API or settings UI
protected_branches:
  main:
    push_access_level: maintainer
    merge_access_level: developer
    unprotect_access_level: admin
    code_owner_approval_required: true

merge_request_approvals:
  approvals_before_merge: 2
  reset_approvals_on_push: true
```

## Automated Testing

### Pre-merge Checks

```yaml
# .github/workflows/pr-checks.yml
name: PR Checks

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Check PR size
        run: |
          LINES=$(git diff --numstat origin/main...HEAD | awk '{sum += $1 + $2} END {print sum}')
          if [ "$LINES" -gt 1000 ]; then
            echo "::warning::Large PR ($LINES lines). Consider splitting."
          fi

      - name: Check commit messages
        run: |
          git log origin/main..HEAD --pretty=format:"%s" | while read msg; do
            if ! echo "$msg" | grep -qE "^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)"; then
              echo "::error::Invalid commit message: $msg"
              exit 1
            fi
          done

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test -- --coverage --changedSince=origin/main

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run lint -- --max-warnings 0
```

### E2E Testing

```yaml
name: E2E Tests

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  e2e:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_DB: test
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
        ports:
          - 5432:5432

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm ci

      - name: Start application
        run: npm start &
        env:
          DATABASE_URL: postgres://test:test@localhost:5432/test

      - name: Wait for app
        run: npx wait-on http://localhost:3000

      - name: Run E2E tests
        run: npm run test:e2e

      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: e2e-screenshots
          path: cypress/screenshots/
```

## Deployment Strategies

### Blue-Green Deployment

```yaml
name: Blue-Green Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to green
        run: |
          kubectl apply -f k8s/green-deployment.yaml
          kubectl rollout status deployment/app-green

      - name: Run smoke tests
        run: ./scripts/smoke-test.sh green

      - name: Switch traffic
        run: |
          kubectl patch service app -p '{"spec":{"selector":{"version":"green"}}}'

      - name: Cleanup blue
        run: |
          kubectl delete deployment app-blue || true
```

### Canary Deployment

```yaml
name: Canary Deploy

on:
  push:
    branches: [main]

jobs:
  canary:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy canary (10%)
        run: |
          kubectl apply -f k8s/canary-deployment.yaml
          kubectl set image deployment/app-canary app=${{ env.IMAGE }}

      - name: Monitor canary
        run: |
          sleep 300  # 5 minutes
          ERROR_RATE=$(./scripts/get-error-rate.sh canary)
          if [ "$ERROR_RATE" -gt 5 ]; then
            echo "High error rate, rolling back"
            kubectl rollout undo deployment/app-canary
            exit 1
          fi

      - name: Full rollout
        run: |
          kubectl set image deployment/app app=${{ env.IMAGE }}
          kubectl rollout status deployment/app
```

## Notifications

### Slack Integration

```yaml
name: CI with Notifications

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

      - name: Notify Slack on failure
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "Build failed on ${{ github.ref }}",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "*Build Failed* :x:\n*Branch:* ${{ github.ref }}\n*Commit:* ${{ github.sha }}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>"
                  }
                }
              ]
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
```

## Best Practices

1. **Fast Feedback**: Keep CI under 10 minutes
2. **Parallel Jobs**: Run independent jobs concurrently
3. **Caching**: Cache dependencies and build artifacts
4. **Fail Fast**: Stop on first failure in PR checks
5. **Environment Parity**: Match CI environment to production
6. **Secrets Management**: Use encrypted secrets, rotate regularly
7. **Artifact Retention**: Clean up old artifacts
8. **Status Checks**: Require all checks to pass before merge

```

### references/advanced-git.md

```markdown
# Advanced Git Operations

## Rewriting History

### Interactive Rebase

```bash
# Rebase last N commits
git rebase -i HEAD~5

# Rebase from a specific commit
git rebase -i abc1234^

# Commands available:
# p, pick   - use commit
# r, reword - edit commit message
# e, edit   - stop for amending
# s, squash - combine with previous (keep message)
# f, fixup  - combine with previous (discard message)
# d, drop   - remove commit
# x, exec   - run shell command
```

### Squashing Commits

```bash
# Squash last 3 commits
git rebase -i HEAD~3
# Change 'pick' to 'squash' for commits to combine

# Squash into a specific commit
git rebase -i <commit-before-first-to-squash>^

# Auto-squash fixup commits
git commit --fixup=<commit-hash>
git rebase -i --autosquash main
```

### Splitting Commits

```bash
# Start interactive rebase
git rebase -i HEAD~3

# Mark commit to split with 'edit'
# When stopped at that commit:
git reset HEAD^
git add file1.js
git commit -m "feat: first change"
git add file2.js
git commit -m "feat: second change"
git rebase --continue
```

### Reordering Commits

```bash
# Interactive rebase
git rebase -i HEAD~5

# In editor, reorder lines to reorder commits
# Example:
# pick abc1234 feat: feature A
# pick def5678 feat: feature B
# Changes to:
# pick def5678 feat: feature B
# pick abc1234 feat: feature A
```

## Cherry-Picking

### Basic Cherry-Pick

```bash
# Pick a single commit
git cherry-pick abc1234

# Pick multiple commits
git cherry-pick abc1234 def5678 ghi9012

# Pick a range
git cherry-pick abc1234^..def5678

# Cherry-pick without committing
git cherry-pick -n abc1234
```

### Cherry-Pick Options

```bash
# Keep original author
git cherry-pick -x abc1234

# Sign off
git cherry-pick -s abc1234

# Edit commit message
git cherry-pick -e abc1234

# Continue after conflict
git cherry-pick --continue

# Abort cherry-pick
git cherry-pick --abort
```

### Cherry-Pick Workflow

```bash
# Backport fix to release branch
git checkout release/1.0
git cherry-pick abc1234  # Fix from main
git push origin release/1.0

# Apply multiple fixes
git cherry-pick abc1234 def5678
# Or create a cherry-pick branch
git checkout -b cherry-pick-fixes release/1.0
git cherry-pick abc1234 def5678
git checkout release/1.0
git merge --no-ff cherry-pick-fixes
```

## Stashing

### Basic Stash Operations

```bash
# Stash current changes
git stash

# Stash with message
git stash save "Work in progress on feature X"

# List stashes
git stash list

# Apply latest stash (keep in stash list)
git stash apply

# Apply and remove from stash list
git stash pop

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

# Drop a stash
git stash drop stash@{1}

# Clear all stashes
git stash clear
```

### Advanced Stashing

```bash
# Stash including untracked files
git stash -u

# Stash including ignored files
git stash -a

# Stash specific files
git stash push -m "message" file1.js file2.js

# Create branch from stash
git stash branch new-branch stash@{0}

# Show stash contents
git stash show stash@{0}
git stash show -p stash@{0}  # With diff

# Partial stash (interactive)
git stash -p
```

## Bisecting

### Finding Bug Introduction

```bash
# Start bisect
git bisect start

# Mark current as bad
git bisect bad

# Mark known good commit
git bisect good v1.0.0

# Git will checkout middle commit
# Test, then mark:
git bisect good  # If bug not present
git bisect bad   # If bug present

# Continue until found
# Git reports: "abc1234 is the first bad commit"

# End bisect
git bisect reset
```

### Automated Bisect

```bash
# Run script at each step
git bisect start HEAD v1.0.0
git bisect run npm test

# With custom script
git bisect run ./test-for-bug.sh

# Exit codes:
# 0     - good
# 1-124 - bad
# 125   - skip (can't test this commit)
# 126+  - abort bisect
```

### Bisect Log

```bash
# Show bisect log
git bisect log

# Save bisect log
git bisect log > bisect.log

# Replay bisect
git bisect replay bisect.log
```

## Reflog

### Understanding Reflog

```bash
# Show reflog
git reflog

# Show reflog for specific ref
git reflog show main
git reflog show HEAD

# Output:
# abc1234 HEAD@{0}: commit: feat: add feature
# def5678 HEAD@{1}: checkout: moving from main to feature
# ghi9012 HEAD@{2}: commit: fix: bug fix
```

### Recovering Lost Commits

```bash
# Find lost commit in reflog
git reflog

# Recover commit
git checkout abc1234
git checkout -b recovered-branch

# Or cherry-pick
git cherry-pick abc1234

# Recover after bad reset
git reflog
git reset --hard HEAD@{2}
```

### Reflog Expiration

```bash
# Default: 90 days for reachable, 30 for unreachable
git config gc.reflogExpire 90.days
git config gc.reflogExpireUnreachable 30.days

# Expire reflog manually
git reflog expire --expire=now --all
git gc --prune=now
```

## Worktrees

### Multiple Working Directories

```bash
# Add worktree
git worktree add ../project-feature feature-branch

# Add worktree with new branch
git worktree add -b new-feature ../project-new-feature main

# List worktrees
git worktree list

# Remove worktree
git worktree remove ../project-feature

# Prune stale worktree info
git worktree prune
```

### Use Cases

```bash
# Work on hotfix while keeping feature work
git worktree add ../project-hotfix hotfix/critical-bug
cd ../project-hotfix
# Fix bug
git commit -am "fix: critical bug"
cd ../project-main

# Review PR without stashing
git worktree add ../pr-review origin/feature-branch
cd ../pr-review
# Review code
```

## Submodules

### Adding Submodules

```bash
# Add submodule
git submodule add https://github.com/org/repo.git libs/repo

# Add at specific branch
git submodule add -b main https://github.com/org/repo.git libs/repo

# Initialize submodules after clone
git submodule init
git submodule update

# Clone with submodules
git clone --recurse-submodules https://github.com/org/main-repo.git
```

### Updating Submodules

```bash
# Update all submodules to latest
git submodule update --remote

# Update specific submodule
git submodule update --remote libs/repo

# Update and merge
git submodule update --remote --merge

# Pull in main repo and submodules
git pull --recurse-submodules
```

### Submodule Commands

```bash
# Run command in all submodules
git submodule foreach 'git pull origin main'

# Check status
git submodule status

# Remove submodule
git submodule deinit libs/repo
git rm libs/repo
rm -rf .git/modules/libs/repo
```

## Git Hooks

### Client-Side Hooks

```bash
# .git/hooks/pre-commit
#!/bin/bash
npm run lint
npm run test

# .git/hooks/commit-msg
#!/bin/bash
# Validate commit message format

# .git/hooks/pre-push
#!/bin/bash
npm run test:e2e
```

### Server-Side Hooks

```bash
# hooks/pre-receive
#!/bin/bash
# Validate pushes before accepting

# hooks/post-receive
#!/bin/bash
# Deploy after push accepted

# hooks/update
#!/bin/bash
# Per-branch validation
```

### Hook Management with Husky

```json
// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
      "pre-push": "npm test"
    }
  },
  "lint-staged": {
    "*.{js,ts}": ["eslint --fix", "prettier --write"]
  }
}
```

## Advanced Merging

### Merge Strategies

```bash
# Recursive (default)
git merge feature

# Ours (keep our changes)
git merge -s ours feature

# Subtree (merge into subdirectory)
git merge -s subtree --allow-unrelated-histories other-repo/main

# Octopus (merge multiple branches)
git merge feature1 feature2 feature3
```

### Merge Options

```bash
# No fast-forward
git merge --no-ff feature

# Squash merge
git merge --squash feature

# Merge with message
git merge -m "Merge feature X" feature

# Abort merge
git merge --abort
```

### Rerere (Reuse Recorded Resolution)

```bash
# Enable rerere
git config rerere.enabled true

# After resolving conflict, it's recorded
# Next time same conflict occurs, auto-resolved

# View recorded resolutions
git rerere status

# Forget resolution
git rerere forget path/to/file
```

## Git Attributes

### Line Endings

```bash
# .gitattributes
* text=auto
*.sh text eol=lf
*.bat text eol=crlf
*.png binary
```

### Diff and Merge

```bash
# .gitattributes
*.min.js binary
*.lock -diff
*.pdf diff=pdf

# Custom diff driver
[diff "pdf"]
  textconv = pdftotext -layout
```

### Export Ignore

```bash
# .gitattributes
.gitignore export-ignore
.github export-ignore
tests/ export-ignore
```

## Performance Optimization

### Large Repositories

```bash
# Shallow clone
git clone --depth 1 https://github.com/org/repo.git

# Sparse checkout
git clone --filter=blob:none --sparse https://github.com/org/repo.git
cd repo
git sparse-checkout set src/

# Partial clone
git clone --filter=blob:none https://github.com/org/repo.git
```

### Git LFS

```bash
# Install LFS
git lfs install

# Track large files
git lfs track "*.psd"
git lfs track "*.zip"

# View tracked patterns
git lfs track

# View LFS files
git lfs ls-files

# Pull LFS files
git lfs pull
```

### Repository Maintenance

```bash
# Garbage collection
git gc

# Aggressive gc
git gc --aggressive

# Prune unreachable objects
git prune

# Verify repository
git fsck

# Repack
git repack -a -d
```

## Troubleshooting

### Common Issues

```bash
# Fix "detached HEAD"
git checkout -b new-branch  # If you want to keep changes
git checkout main           # If you want to discard

# Fix "refusing to merge unrelated histories"
git merge --allow-unrelated-histories other-branch

# Fix corrupted repository
git fsck --full
git gc --prune=now

# Remove file from all history
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch path/to/file' \
  --prune-empty --tag-name-filter cat -- --all
```

### Recovery Operations

```bash
# Recover deleted branch
git reflog
git checkout -b recovered abc1234

# Recover deleted file
git checkout HEAD~1 -- path/to/file

# Undo hard reset
git reflog
git reset --hard HEAD@{1}

# Recover stash
git fsck --unreachable | grep commit | cut -d' ' -f3 | \
  xargs git log --merges --no-walk --grep=WIP
```

```

### references/github-releases.md

```markdown
# GitHub Releases Reference

**Purpose:** Document GitHub release management, immutable releases security feature, and release sequence patterns.

---

## Immutable Releases Security Feature

### Overview

**GitHub Immutable Releases** (GA October 2024) is a permanent security feature that prevents tag name reuse after a release is deleted.

**Security Purpose:** Prevents supply chain attacks where an attacker could:
1. Delete a legitimate release
2. Create a new release with the same version containing malicious code
3. Users downloading "v1.2.3" would get the malicious version

### Behavior

| Action | Result |
|--------|--------|
| Create release v1.2.3 | ✅ Success |
| Delete release v1.2.3 | ✅ Allowed |
| Create NEW release v1.2.3 | ❌ PERMANENTLY BLOCKED |
| Create release v1.2.4 | ✅ Success (new version) |

### Key Facts

- **Cannot be disabled:** No repository setting, API call, or GitHub support request can bypass this
- **Permanent:** Once blocked, a tag name stays blocked forever
- **Per-repository:** Each repository has its own blocked tag list
- **Applies to:** Published releases only (not draft releases)

### Detection

```bash
# Attempt to create release - if blocked, you'll see:
# "tag_name was used by an immutable release"
gh release create v1.2.3 --notes "test" 2>&1 | grep -i "immutable"
```

---

## Release Sequence Patterns

### TYPO3 Extension Release

**Correct Sequence:**
```bash
# 1. Create release branch
git checkout -b release/v1.2.3

# 2. Update version in source files
# ext_emconf.php
sed -i "s/'version' => '.*'/'version' => '1.2.3'/" ext_emconf.php

# CHANGELOG.md - add new version section

# 3. Commit version bump
git add ext_emconf.php CHANGELOG.md
git commit -m "chore: bump version to 1.2.3"

# 4. Create PR and merge
git push -u origin release/v1.2.3
gh pr create --title "chore: bump version to 1.2.3"
# Wait for CI to pass
gh pr merge --squash

# 5. Switch to main and verify
git checkout main && git pull
grep "'version'" ext_emconf.php  # MUST show 1.2.3

# 6. Create release ONLY after verification
gh release create v1.2.3 \
  --title "v1.2.3" \
  --notes "Release notes here"
```

**Common Mistakes:**
| Mistake | Consequence |
|---------|-------------|
| Create release before updating version | Version mismatch, TER/npm publish fails |
| Create release before merging PR | Tag points to wrong commit |
| Delete release to "fix" something | Tag name permanently blocked |
| Rush without verification | Multiple blocked versions |

### NPM Package Release

```bash
# 1. Update package.json version
npm version patch  # or minor/major

# 2. Verify version
grep '"version"' package.json

# 3. Push changes
git push && git push --tags

# 4. Create GitHub release (if using GitHub releases)
gh release create v$(node -p "require('./package.json').version")
```

### Python Package Release

```bash
# 1. Update version in pyproject.toml or setup.py
# 2. Update CHANGELOG

# 3. Commit and push
git add pyproject.toml CHANGELOG.md
git commit -m "chore: bump version to 1.2.3"
git push

# 4. Create and push tag
git tag v1.2.3
git push --tags

# 5. Create release
gh release create v1.2.3
```

---

## Pre-Release Validation

### Automated Checks

Add to CI workflow:
```yaml
- name: Version Consistency Check
  run: |
    # Extract versions from different sources
    EMCONF_VERSION=$(grep -oP "'version' => '\K[0-9]+\.[0-9]+\.[0-9]+" ext_emconf.php)

    # For tagged builds, verify tag matches
    if [[ "${GITHUB_REF}" =~ ^refs/tags/v ]]; then
      TAG_VERSION="${GITHUB_REF#refs/tags/v}"
      if [[ "${TAG_VERSION}" != "${EMCONF_VERSION}" ]]; then
        echo "::error::Version mismatch! Tag: ${TAG_VERSION}, ext_emconf.php: ${EMCONF_VERSION}"
        exit 1
      fi
    fi
    echo "Version check passed: ${EMCONF_VERSION}"
```

### Manual Checklist

Before creating ANY release:
```
[ ] All code changes merged to main/master
[ ] CI pipeline passes on main branch
[ ] Version updated in ALL source files:
    [ ] ext_emconf.php (TYPO3)
    [ ] package.json (Node)
    [ ] pyproject.toml / setup.py (Python)
    [ ] composer.json (if version is tracked there)
[ ] CHANGELOG.md updated with new version
[ ] Local main is up to date: git pull origin main
[ ] Version verification: grep -r "version" | grep "1.2.3"
[ ] READY - No second chances after release creation!
```

---

## Recovery Procedures

### Scenario: TER/npm/PyPI Publish Failed After Release

**DO NOT DELETE THE RELEASE!**

Instead:
1. Identify the root cause of publish failure
2. Fix the issue in a new commit
3. Update version to NEXT number (skipping the broken version)
4. Create new release with new version

Example:
```bash
# v1.2.3 release created but TER publish failed
# DO NOT: gh release delete v1.2.3

# Fix the issue
vim ext_emconf.php  # remove strict_types or fix other issues

# Bump to NEXT version
sed -i "s/'version' => '1.2.3'/'version' => '1.2.4'/" ext_emconf.php

# Update CHANGELOG
cat >> CHANGELOG.md << 'EOF'
## [1.2.4] - 2025-01-15

### Fixed
- Fixed TER publishing issue (strict_types in ext_emconf.php)

Note: v1.2.3 was skipped due to publish failure.
EOF

# Commit, merge, then create new release
git add -A && git commit -m "fix: resolve TER publish issue, bump to 1.2.4"
git push && gh pr create && gh pr merge
gh release create v1.2.4 --notes "..."
```

### Scenario: Multiple Versions Blocked

If you've blocked v1.2.3, v1.2.4, v1.2.5 through repeated failures:

1. **Stop and think** - don't create more releases
2. List what went wrong each time
3. Fix ALL issues before next attempt
4. Use next available version (v1.2.6)
5. Document skipped versions in CHANGELOG

```markdown
## [1.2.6] - 2025-01-15

Note: Versions 1.2.3-1.2.5 are unavailable due to GitHub's immutable
releases feature. These versions were blocked after release deletion
attempts during troubleshooting.

### Fixed
- Resolved TER compatibility issue with ext_emconf.php
```

---

## Best Practices

### Do
- ✅ Update version files BEFORE creating release
- ✅ Verify version with grep before release
- ✅ Use CI checks for version consistency
- ✅ Keep releases - never delete published releases
- ✅ Test publish process in staging first (if possible)

### Don't
- ❌ Create release before version is updated in source
- ❌ Delete releases to "fix" issues
- ❌ Rush releases without verification
- ❌ Assume you can recreate a deleted release
- ❌ Create multiple releases hoping one will work

---

## Resources

- **GitHub Blog:** Immutable Releases announcement
- **GitHub Docs:** Managing releases in a repository
- **TYPO3 TER:** Extension publishing requirements

```

### scripts/verify-git-workflow.sh

```bash
#!/bin/bash
# Git Workflow Verification Script
# Checks repository for git workflow best practices

set -e

REPO_DIR="${1:-.}"
ERRORS=0
WARNINGS=0

echo "=== Git Workflow Verification ==="
echo "Repository: $REPO_DIR"
echo ""

# Change to repo directory
cd "$REPO_DIR"

# Check if it's a git repository
if [[ ! -d ".git" ]]; then
    echo "❌ Not a git repository"
    exit 1
fi

# Check branch naming
echo "=== Branch Naming Convention ==="
BRANCHES=$(git branch -a 2>/dev/null | sed 's/^[* ]*//' | grep -v "HEAD" | sed 's/remotes\/origin\///' | sort -u)

VALID_PATTERN="^(main|master|develop|feature\/|fix\/|bugfix\/|hotfix\/|release\/|chore\/|docs\/|test\/|refactor\/)"
INVALID_BRANCHES=""

for branch in $BRANCHES; do
    if ! echo "$branch" | grep -qE "$VALID_PATTERN"; then
        INVALID_BRANCHES="$INVALID_BRANCHES $branch"
    fi
done

if [[ -n "$INVALID_BRANCHES" ]]; then
    echo "⚠️  Non-standard branch names found:"
    echo "  $INVALID_BRANCHES"
    echo "   Expected: main, develop, feature/*, fix/*, release/*, hotfix/*"
    ((WARNINGS++))
else
    echo "✅ All branch names follow conventions"
fi

# Check commit message format
echo ""
echo "=== Commit Message Format ==="
RECENT_COMMITS=$(git log --oneline -20 2>/dev/null | head -20)

CONV_PATTERN="^[a-f0-9]+ (feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?(!)?: .+"
INVALID_COMMITS=0
VALID_COMMITS=0

while IFS= read -r commit; do
    if echo "$commit" | grep -qE "$CONV_PATTERN"; then
        ((VALID_COMMITS++))
    else
        # Allow merge commits
        if ! echo "$commit" | grep -qE "^[a-f0-9]+ Merge"; then
            ((INVALID_COMMITS++))
        fi
    fi
done <<< "$RECENT_COMMITS"

TOTAL_COMMITS=$((VALID_COMMITS + INVALID_COMMITS))
if [[ $TOTAL_COMMITS -gt 0 ]]; then
    PERCENT=$((VALID_COMMITS * 100 / TOTAL_COMMITS))
    if [[ $PERCENT -ge 80 ]]; then
        echo "✅ $PERCENT% of commits follow Conventional Commits format"
    elif [[ $PERCENT -ge 50 ]]; then
        echo "⚠️  $PERCENT% of commits follow Conventional Commits format"
        ((WARNINGS++))
    else
        echo "⚠️  Only $PERCENT% of commits follow Conventional Commits format"
        ((WARNINGS++))
    fi
fi

# Check for .gitignore
echo ""
echo "=== .gitignore Check ==="
if [[ -f ".gitignore" ]]; then
    echo "✅ .gitignore exists"

    # Check for common patterns
    COMMON_IGNORES=("node_modules" ".env" "*.log" "dist" "build" ".DS_Store")
    MISSING_IGNORES=""

    for pattern in "${COMMON_IGNORES[@]}"; do
        if ! grep -q "$pattern" .gitignore 2>/dev/null; then
            MISSING_IGNORES="$MISSING_IGNORES $pattern"
        fi
    done

    if [[ -n "$MISSING_IGNORES" ]]; then
        echo "   ℹ️  Consider adding:$MISSING_IGNORES"
    fi
else
    echo "⚠️  No .gitignore file found"
    ((WARNINGS++))
fi

# Check for hooks
echo ""
echo "=== Git Hooks ==="
if [[ -d ".git/hooks" ]]; then
    ACTIVE_HOOKS=$(find .git/hooks -type f ! -name "*.sample" 2>/dev/null | wc -l)
    if [[ $ACTIVE_HOOKS -gt 0 ]]; then
        echo "✅ Found $ACTIVE_HOOKS active hook(s)"
        find .git/hooks -type f ! -name "*.sample" -exec basename {} \; 2>/dev/null | sed 's/^/   /'
    else
        echo "ℹ️  No active git hooks"
    fi
fi

# Check for husky
if [[ -d ".husky" ]]; then
    echo "✅ Husky hooks directory found"
fi

# Check for commitlint
if [[ -f "commitlint.config.js" ]] || [[ -f ".commitlintrc" ]] || [[ -f ".commitlintrc.json" ]]; then
    echo "✅ Commitlint configuration found"
fi

# Check for branch protection (via CODEOWNERS)
echo ""
echo "=== Code Ownership ==="
if [[ -f "CODEOWNERS" ]] || [[ -f ".github/CODEOWNERS" ]] || [[ -f "docs/CODEOWNERS" ]]; then
    echo "✅ CODEOWNERS file found"
else
    echo "ℹ️  No CODEOWNERS file (optional)"
fi

# Check for PR template
echo ""
echo "=== PR Templates ==="
if [[ -f ".github/PULL_REQUEST_TEMPLATE.md" ]] || [[ -d ".github/PULL_REQUEST_TEMPLATE" ]]; then
    echo "✅ PR template(s) found"
else
    echo "ℹ️  No PR template (recommended)"
fi

# Check for CI/CD configuration
echo ""
echo "=== CI/CD Configuration ==="
CI_FOUND=false

if [[ -d ".github/workflows" ]]; then
    WORKFLOW_COUNT=$(find .github/workflows -name "*.yml" -o -name "*.yaml" 2>/dev/null | wc -l)
    if [[ $WORKFLOW_COUNT -gt 0 ]]; then
        echo "✅ GitHub Actions: $WORKFLOW_COUNT workflow(s)"
        CI_FOUND=true
    fi
fi

if [[ -f ".gitlab-ci.yml" ]]; then
    echo "✅ GitLab CI configuration found"
    CI_FOUND=true
fi

if [[ -f "Jenkinsfile" ]]; then
    echo "✅ Jenkinsfile found"
    CI_FOUND=true
fi

if [[ -f ".circleci/config.yml" ]]; then
    echo "✅ CircleCI configuration found"
    CI_FOUND=true
fi

if [[ -f "azure-pipelines.yml" ]]; then
    echo "✅ Azure Pipelines configuration found"
    CI_FOUND=true
fi

if [[ "$CI_FOUND" == "false" ]]; then
    echo "⚠️  No CI/CD configuration found"
    ((WARNINGS++))
fi

# Check for semantic release
echo ""
echo "=== Release Configuration ==="
if [[ -f ".releaserc" ]] || [[ -f ".releaserc.json" ]] || [[ -f ".releaserc.yml" ]] || [[ -f "release.config.js" ]]; then
    echo "✅ Semantic release configuration found"
fi

# Check for CHANGELOG
if [[ -f "CHANGELOG.md" ]] || [[ -f "CHANGELOG" ]]; then
    echo "✅ CHANGELOG found"
else
    echo "ℹ️  No CHANGELOG (recommended for releases)"
fi

# Check for versioning
if [[ -f "package.json" ]]; then
    VERSION=$(grep '"version"' package.json | head -1 | sed 's/.*: *"\([^"]*\)".*/\1/')
    if [[ -n "$VERSION" ]]; then
        echo "✅ Package version: $VERSION"
    fi
fi

# Check current branch
echo ""
echo "=== Current State ==="
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)
echo "Current branch: $CURRENT_BRANCH"

# Check for uncommitted changes
if git diff --quiet 2>/dev/null && git diff --cached --quiet 2>/dev/null; then
    echo "✅ Working directory clean"
else
    CHANGES=$(git status --porcelain 2>/dev/null | wc -l)
    echo "⚠️  $CHANGES uncommitted change(s)"
fi

# Check if up to date with remote
if git remote | grep -q "origin" 2>/dev/null; then
    git fetch origin --quiet 2>/dev/null || true
    LOCAL=$(git rev-parse "$CURRENT_BRANCH" 2>/dev/null)
    REMOTE=$(git rev-parse "origin/$CURRENT_BRANCH" 2>/dev/null) || true

    if [[ -n "$REMOTE" ]]; then
        if [[ "$LOCAL" == "$REMOTE" ]]; then
            echo "✅ Up to date with origin/$CURRENT_BRANCH"
        else
            BEHIND=$(git rev-list --count "$LOCAL..$REMOTE" 2>/dev/null)
            AHEAD=$(git rev-list --count "$REMOTE..$LOCAL" 2>/dev/null)
            echo "ℹ️  Branch is $AHEAD ahead, $BEHIND behind origin/$CURRENT_BRANCH"
        fi
    fi
fi

# Check for merge conflicts markers
echo ""
echo "=== Conflict Markers ==="
CONFLICT_FILES=$(grep -rln "<<<<<<< \|======= \|>>>>>>> " --include="*.js" --include="*.ts" --include="*.php" --include="*.py" . 2>/dev/null | grep -v node_modules | grep -v vendor | head -5)
if [[ -n "$CONFLICT_FILES" ]]; then
    echo "❌ Conflict markers found in files:"
    echo "$CONFLICT_FILES" | sed 's/^/   /'
    ((ERRORS++))
else
    echo "✅ No conflict markers found"
fi

# Summary
echo ""
echo "=== Summary ==="
echo "Errors: $ERRORS"
echo "Warnings: $WARNINGS"

if [[ $ERRORS -gt 0 ]]; then
    echo "❌ Verification FAILED"
    exit 1
elif [[ $WARNINGS -gt 3 ]]; then
    echo "⚠️  Verification completed with warnings"
    exit 0
else
    echo "✅ Verification PASSED"
    exit 0
fi

```

git-workflow | SkillHub