Solo Developers & Teams

Managing Projects with Git, GSD & Skill Creator

A complete guide to version control, branching strategies, team collaboration, inbox processing, and the folder structures that hold it all together — from your first commit to production deployment.

Part One

Understanding Git

01

Why Git Matters

Git is a version control system. It tracks every change you make to your files and lets you go back to any previous version. Think of it as an infinite undo history that also lets multiple people work on the same project simultaneously without overwriting each other's work.

When combined with GSD and Skill Creator, Git becomes the backbone of the entire system. GSD makes atomic commits after every completed task. Skill Creator's post-commit hooks observe those commits to detect patterns. The DACP system uses Git state to determine handoff context. Without Git, none of this works.

If you're coming to Git for the first time, the next section will get you up to speed. If you already know Git, skip to section 03.

02

Git in 10 Minutes

The Three Places Your Files Live

Git has three areas that files move between. Understanding these three areas is the single most important concept in Git:

  Working Directory        Staging Area           Repository
  (your actual files)      (what's about to         (permanent history)
                            be committed)

  You edit files here  ──→  git add  ──→  git commit  ──→  Saved forever
                            (pick what                     (snapshot with
                             to include)                    a message)
    

Working directory is just your files on disk. Edit them however you like.

Staging area (also called "index") is where you assemble what you want to save. You pick and choose which changes to include. This is powerful — if you changed 5 files but only want to save 3 of them right now, you stage those 3.

Repository is the permanent record. Once committed, a change is (almost) impossible to lose.

Essential Commands

# Create a new git repository in the current folder
git init

# See what's changed since the last commit
git status

# Stage specific files for the next commit
git add src/app.ts src/types.ts

# Stage everything that's changed
git add .

# Commit the staged changes with a message
git commit -m "feat(auth): add login form with email validation"

# See the history of commits
git log --oneline

# See what changed in a file
git diff src/app.ts
The golden rule: commit often, with clear messages. A commit should represent one logical change — "add login form," "fix password validation bug," "update user schema." If your commit message needs the word "and" in it, you're probably bundling too much into one commit.

Reading Git Status

When you run git status, Git tells you exactly what's going on:

# Untracked files — Git has never seen these before
Untracked files:
  src/new-feature.ts

# Modified — changed since last commit, but not staged yet
Changes not staged for commit:
  modified: src/app.ts

# Staged — ready to be committed
Changes to be committed:
  new file: src/types.ts
  modified: src/utils.ts

Undoing Things

# Unstage a file (keep the changes, just remove from staging)
git restore --staged src/app.ts

# Discard changes to a file (go back to last committed version)
git restore src/app.ts

# Go back to a previous commit (look at it, don't change anything)
git log --oneline       # find the commit hash
git checkout abc1234    # visit that point in time
git checkout main       # come back to the present
03

Branching & Merging

A branch is a parallel version of your project. You create a branch, make changes on it, and when you're satisfied, merge those changes back into the main line. The original branch is untouched until you decide to integrate.

Why Branch?

Without branches, every change you make affects everyone immediately. If you're building a new feature and it's half-finished, the whole project is in a broken state. Branches let you work in isolation — you can break things, experiment, and iterate without affecting anyone else (or your own stable codebase).

Creating and Switching Branches

# Create a new branch and switch to it
git checkout -b feature/user-dashboard

# This is shorthand for two commands:
git branch feature/user-dashboard    # create it
git checkout feature/user-dashboard   # switch to it

# List all branches (* marks the current one)
git branch
  * feature/user-dashboard
    main

# Switch back to main
git checkout main

Branch Naming Conventions

Good branch names tell you what the branch is for at a glance:

PrefixPurposeExample
feature/New functionalityfeature/user-dashboard
fix/Bug fixesfix/login-redirect-loop
hotfix/Urgent production fixeshotfix/payment-crash
chore/Maintenance, cleanupchore/update-dependencies
docs/Documentationdocs/api-reference
refactor/Code restructuringrefactor/extract-auth-module

Merging a Branch

When your feature is done, you bring those changes back into main:

# 1. Switch to the branch you want to merge INTO
git checkout main

# 2. Merge the feature branch into main
git merge feature/user-dashboard

# 3. Delete the branch (it's been merged, you don't need it)
git branch -d feature/user-dashboard

If nobody else changed main while you were working, Git does a "fast-forward merge" — it just moves the pointer ahead. No merge commit needed. If main did change, Git creates a merge commit that combines both histories.

04

Resolving Merge Conflicts

A merge conflict happens when two branches changed the same lines in the same file. Git can't automatically decide whose version to keep, so it asks you.

What a Conflict Looks Like

When Git finds a conflict during a merge, it marks the file with conflict markers:

function getGreeting(name: string) {
<<<<<<< HEAD
  return `Hello, ${name}! Welcome back.`;
=======
  return `Hey ${name}, good to see you!`;
>>>>>>> feature/casual-greetings
}

The file now has three sections:

How to Resolve

You resolve a conflict by editing the file to be exactly what you want. Remove the conflict markers and choose (or combine) the code:

// Option A: Keep your version
function getGreeting(name: string) {
  return `Hello, ${name}! Welcome back.`;
}

// Option B: Keep theirs
function getGreeting(name: string) {
  return `Hey ${name}, good to see you!`;
}

// Option C: Combine both (this is the most common choice)
function getGreeting(name: string, casual = false) {
  return casual
    ? `Hey ${name}, good to see you!`
    : `Hello, ${name}! Welcome back.`;
}

After editing, tell Git the conflict is resolved:

git add src/greeting.ts        # mark as resolved
git commit                      # complete the merge
Preventing conflicts: The best way to handle conflicts is to avoid them. Keep branches short-lived (merge within a few days, not weeks). Pull from main frequently. Communicate with your team about which files you're working on.

Aborting a Merge

If a merge gets too messy and you want to start over:

git merge --abort    # go back to before the merge started
05

Versioning & Tags

Tags mark specific points in your history as important — usually releases. While branches move forward as you add commits, tags are permanent bookmarks.

Semantic Versioning

The standard format is MAJOR.MINOR.PATCH:

PartWhen to IncrementExample
MAJORBreaking changes that require users to update their code1.0.0 → 2.0.0
MINORNew features that are backward-compatible1.0.0 → 1.1.0
PATCHBug fixes, no new features1.1.0 → 1.1.1

Creating Tags

# Create an annotated tag (recommended — includes message and author)
git tag -a v1.2.0 -m "Release 1.2.0: add user dashboard and API caching"

# List all tags
git tag

# See details about a specific tag
git show v1.2.0

# Check out a specific release
git checkout v1.2.0

Skill Creator uses this exact convention — v1.49.6 means major version 1, minor version 49, patch 6. The CHANGELOG maps each version to its phase count, test count, and shipped features.

06

Git Worktrees

A worktree lets you have multiple branches checked out simultaneously in different directories, all sharing the same repository. Instead of switching branches (which replaces all your files), you just open a different folder.

Why Worktrees?

Switching branches is disruptive. Your editor reloads. Your dev server restarts. Your build cache invalidates. Worktrees avoid all of this — each branch lives in its own directory, running independently.

# Your main working directory is already on 'main'
# Create a worktree for a feature branch in a sibling directory
git worktree add ../my-project-feature feature/user-dashboard

# Now you have:
#   ~/projects/my-project/           ← main branch
#   ~/projects/my-project-feature/   ← feature branch

# Both are the same repository — commits in either appear in both

# List all worktrees
git worktree list

# When done, remove the worktree
git worktree remove ../my-project-feature

Worktrees + GSD

Worktrees are especially powerful with GSD because each worktree can run its own GSD session. You can have one agent executing Phase 12 in the main worktree while another agent runs tests on Phase 11's output in a feature worktree. The sessions don't interfere because they're in different directories.

Skill Creator v1.38 formalized this as per-agent worktree isolation: each agent type (exec, verify, scout, main) gets its own worktree with a scoped sandbox profile. Cross-agent read access is denied by default, with only the INTEG (integration) role having read-only access across all worktrees. This prevents a compromised agent from accessing credentials or modifying another agent's work.

07

Dev → Alpha → Beta → Prod

For projects with deployment stages, a multi-environment branching strategy keeps unstable code away from users:

  feature/* ──→ dev ──→ alpha ──→ beta ──→ main (prod)
  (wild west)     (integration)  (internal      (external     (stable,
                                  testing)       testing)      deployed)
    
BranchWho Uses ItStabilityMerges From
feature/*Individual developersMay be brokenCreated from dev
devAll developersCompiles, tests passMerged features
alphaInternal teamFeature-complete, may have bugsPromoted from dev
betaExternal testersRelease candidate, minor bugsPromoted from alpha
mainEnd usersProduction-readyPromoted from beta

Promotion Flow

# Developer finishes a feature
git checkout dev
git merge feature/new-widget
git branch -d feature/new-widget

# When dev is stable enough for internal testing
git checkout alpha
git merge dev
git tag -a v2.1.0-alpha.1 -m "Alpha 1: widget + dashboard"

# After internal testing passes
git checkout beta
git merge alpha
git tag -a v2.1.0-beta.1 -m "Beta 1: tested internally"

# After beta feedback is addressed
git checkout main
git merge beta
git tag -a v2.1.0 -m "Release 2.1.0"

Hotfixes

When a critical bug hits production, you branch directly from main, fix it, merge it back, then forward-merge the fix through beta, alpha, and dev so everyone has it:

git checkout -b hotfix/payment-crash main
# ... fix the bug ...
git checkout main  && git merge hotfix/payment-crash
git checkout beta  && git merge main
git checkout alpha && git merge main
git checkout dev   && git merge main
git branch -d hotfix/payment-crash
Not every project needs all these stages. A solo developer might use just main + feature/*. A small team might add dev. The full pipeline is for projects with external users and deployment infrastructure.
Part Two

GSD & Skill Creator Integration

08

How GSD Uses Git

GSD doesn't just use Git for storage — Git is part of the execution model. Here's what happens behind the scenes:

Atomic Task Commits

After every completed task within a plan, GSD creates a git commit. Not after every phase, not after every milestone — after every task. This gives you an extremely fine-grained history. If task 3 of 5 introduced a regression, you can identify exactly which commit caused it and revert just that change.

Commits follow the Conventional Commits format, enforced by a git hook:

feat(auth): add email validation to login form
fix(api): handle null response from user service
test(dashboard): add integration tests for chart rendering
docs(readme): update installation instructions

The format is type(scope): description, where type is one of: feat, fix, docs, style, refactor, perf, test, build, ci, chore. The validate-commit hook blocks any commit that doesn't match this pattern.

Git State Awareness

Skill Creator includes a git-state-check script that produces a JSON report of the repository's state at any moment. It detects six states in priority order: CONFLICT (unresolved merge conflicts), MERGING (mid-merge), REBASING (mid-rebase), DETACHED (not on a branch), DIRTY (uncommitted changes), and CLEAN. The report includes branch name, remote tracking info, ahead/behind counts, and lists of staged, unstaged, and untracked files.

This state report feeds into the session hooks and pattern detection system. If you start a GSD session with dirty files, the system knows. If you're mid-rebase, it warns you before starting execution.

Session State Hooks

On every session start, a hook reads .planning/STATE.md and injects it into the context. This is how GSD remembers where it left off — the hook feeds the agent the current phase, any blockers, and the project configuration. A post-commit hook observes every commit and appends it to sessions.jsonl for pattern analysis.

09

Skill Creator Folder Structure

As of v1.49.5, the repository is organized into zones following Linux FHS conventions. Understanding this layout helps you navigate projects and know where things belong.

The Zone System (v1.49.4)

ZonePathPurpose
projects/projects/Your GSD projects. Each subdirectory is an independent project with its own .planning/ state. External projects can be linked via .sc-config.json.
contrib/contrib/Collaboration zone. upstream/ for PRs you send to other repos. downstream/staging/ for PRs you receive. publishing/ for extracted side projects.
packs/packs/Catalog of educational and domain packs. References source directories in src/.
www/www/Web staging. site/ for generated output, tools/ for web tool sources, staging/ for pre-publish review.

The .planning/ Directory

Every GSD project has a .planning/ directory at its root. This is the state machine:

.planning/
├── STATE.md                 # Current position, blockers, context
├── ROADMAP.md               # Phase completion status
├── REQUIREMENTS.md          # What we're building
├── PROJECT.md               # Project definition
├── config.json              # GSD mode and settings
├── staging/                 # Inbox processing pipeline
│   ├── inbox/               # New documents land here
│   ├── checking/            # Being processed
│   ├── attention/           # Needs human review
│   ├── ready/               # Cleared for processing
│   ├── aside/               # Deferred
│   └── queue.jsonl          # Processing queue
├── patterns/                # Observation JSONL logs
├── bus/                     # Filesystem message bus
├── security/                # Security profiles and audit
└── phases/                  # Per-phase plans, summaries, verification
    ├── phase-001-PLAN.md
    ├── phase-001-SUMMARY.md
    ├── phase-001-VERIFICATION.md
    └── ...
    

Skill Storage

Skills live in two locations, with project-level overriding user-level:

ScopePathVisibility
User~/.claude/skills/All your projects
Project.claude/skills/This project only

External Projects via Config

You don't have to keep all projects inside the Skill Creator repo. The .sc-config.json (gitignored, user-local) lets you reference external directories:

{
  "home": "projects",
  "external_projects": [
    { "name": "my-saas-app", "path": "/home/user/code/my-saas-app" },
    { "name": "client-site", "path": "/home/user/code/client-site" }
  ]
}

The sc project list command shows both local and external projects.

10

Inbox Processing Pipeline

The staging pipeline is a document intake system that ensures every piece of input — vision documents, requirements, skill proposals, feature requests — goes through hygiene checking and clarity assessment before entering the build queue.

The Five States

inbox
checking
attention
ready
aside
StateWhat Happens
inboxDocument arrives. A companion .meta.json file is created alongside it with the submission timestamp, source, and status. Nothing has been checked yet.
checkingThe hygiene scanner runs. It looks for YAML code execution risks, path traversal patterns, zip extraction dangers, and other security concerns. Content is classified by familiarity (trusted/known/stranger). A hygiene report is generated with an overall risk level.
attentionIf the hygiene scan flags critical or warning-level risks, the document is moved here and the flow pauses. A human must review the findings before the document can proceed. This is a hard gate — no automatic bypass.
readyThe document passed hygiene and clarity assessment. It's been confirmed by the user (the "anything else?" prompt) and is queued for processing.
asideThe user deferred this document. It can be resubmitted to inbox later via the aside → inbox transition.

Valid State Transitions

Not every transition is allowed. The state machine enforces a specific graph:

  inbox  ──→ checking ──→ attention ──→ ready
    │            │   ╲        │   ╲        │
    │            │    ╲       │    ╲       │
    ╰──→ aside ←─╯     ╰──→ aside  ╰──→ aside
         │                     ↑            ↑
         ╰──→ inbox            │            │
              (resubmit)     ready ──→ checking
                             (re-check)
    

Key rules: documents can be set aside from any state. Aside documents can only go back to inbox (start over). Ready documents can be re-checked if something changes. Attention documents can be approved (go to ready), re-checked, or deferred.

The Clarity Assessment

After passing hygiene, documents go through a clarity assessment that routes to one of three paths:

Crash Recovery

The intake flow tracks every step in the metadata file. If the process crashes mid-assessment, resumeIntakeFlow() reads the last completed step and continues from there. You never lose progress through the pipeline.

Part Three

Working With Others

11

Solo Developer Workflow

Even as a solo developer, a structured workflow prevents chaos. Here's the recommended approach:

Scenario

Building a Feature Alone

# 1. Start from main, create a feature branch
git checkout main
git checkout -b feature/notifications

# 2. Initialize a GSD project (if new) or start a new milestone
/gsd:new-project      # or /gsd:new-milestone
/gsd:discuss-phase    # talk through what you want
/gsd:plan-phase       # generate the plan

# 3. Execute — GSD commits atomically after each task
/gsd:execute-phase

# 4. Verify the work
/gsd:verify-work

# 5. When the feature is complete, merge back to main
git checkout main
git merge feature/notifications
git tag -a v1.3.0 -m "Add notification system"
git branch -d feature/notifications

The feature branch protects your main branch. If the feature goes sideways, you can abandon the branch entirely. If it works, you get a clean merge with a complete history of atomic commits.

12

Team Collaboration

When multiple people work together, Git's distributed nature becomes essential. Each person has a complete copy of the repository. They push changes to a shared location (a remote) and pull other people's changes down.

The Shared Remote

# Clone the team repository
git clone https://github.com/team/project.git

# Or if using a shared server (see next section)
git clone ssh://server/repos/project.git

# Push your branch to the remote
git push origin feature/my-feature

# Pull the latest changes from main
git checkout main
git pull origin main

# Keep your feature branch up to date with main
git checkout feature/my-feature
git merge main    # or: git rebase main

Team + GSD Workflow

When a team uses GSD, each developer runs their own GSD sessions on their own feature branches. The .planning/ directory tracks per-person state. The key coordination points:

Skill Creator's Contrib Zone

The contrib/ directory is designed for team collaboration: upstream/ holds PRs you're preparing to send to shared repos, downstream/staging/ holds incoming PRs to review, and publishing/ holds side projects extracted for independent release. sc contrib status shows the count in each direction.

13

Shared Repos Without GitHub

You don't need GitHub, GitLab, or any cloud service. Git works perfectly with a bare repository on a shared filesystem — NFS, a Samba share, or even a USB drive.

Setting Up a Bare Repository

A "bare" repository has no working directory — it's just the Git database. It exists solely as a central point for pushing and pulling.

# On the shared drive (NFS mount, Samba share, etc.)
mkdir /mnt/shared/repos/my-project.git
cd /mnt/shared/repos/my-project.git
git init --bare

# On Developer A's machine — create the project and push
cd ~/projects/my-project
git init
git add .
git commit -m "chore: initial project structure"
git remote add origin /mnt/shared/repos/my-project.git
git push -u origin main

# On Developer B's machine — clone
git clone /mnt/shared/repos/my-project.git ~/projects/my-project

SSH-Based Sharing

If the shared location is on another machine accessible via SSH:

# Create the bare repo on the server
ssh server "mkdir -p /repos/my-project.git && cd /repos/my-project.git && git init --bare"

# Clone via SSH
git clone ssh://server/repos/my-project.git

Local Network Discovery

For small teams on a LAN, you can even serve repos temporarily with Git's built-in server:

# On the machine with the repo (serves it read-only)
git daemon --reuseaddr --base-path=/repos /repos

# Other machines can clone via:
git clone git://192.168.1.50/my-project.git
NFS locking caveat: Git relies on atomic file operations. Most NFS implementations handle this fine, but NFS v3 with poor locking can cause corruption if two people push simultaneously. Use NFS v4 or SSH-based remotes for teams larger than 3–4 people.
14

Git Hooks & Automation

Git hooks are scripts that run automatically at specific points in the Git workflow. Skill Creator ships with several:

The Validate-Commit Hook

Runs before every commit is accepted. It parses the commit message and rejects anything that doesn't follow Conventional Commits format. The regex check enforces: valid type prefix, optional scope in parentheses, colon-space separator, subject line under 72 characters. This hook is POSIX-compatible (works on macOS Bash 3.2).

The Session-State Hook

Runs on every session start. It reads .planning/STATE.md and outputs the first 20 lines as a project state reminder. If no .planning/ exists, it suggests running /gsd:new-project. It also reads the project config to display the current mode.

The Post-Commit Hook

Runs after every successful commit. It appends commit metadata to sessions.jsonl — timestamp, hash, message, files changed. This powers the pattern detection system and the historical trends dashboard (commit type distribution, velocity curves, file hotspots).

Phase Boundary Check

Prevents accidental cross-phase work by checking that the current git state aligns with the active phase in .planning/. If you're supposed to be in Phase 12 but the commit references Phase 11 files, the hook warns you.

Installing Hooks

# GSD installs its hooks automatically during setup
npx get-shit-done-cc@latest    # includes hook installation

# Or manually copy hooks into your project
cp project-claude/hooks/validate-commit.sh .claude/hooks/
cp project-claude/hooks/session-state.sh .claude/hooks/
cp project-claude/hooks/post-commit .git/hooks/
15

Agent Isolation with Worktrees

v1.38 introduced per-agent worktree isolation as a security boundary. This is relevant for teams running multiple AI agents simultaneously on the same repository.

How It Works

Each agent type gets its own git worktree with a scoped sandbox profile:

Agent TypeWorktreeAccess
execOwn worktree, own branchRead/write own files only
verifyOwn worktree, read-only checkoutRead everything, write nothing
scoutOwn worktree, ephemeralRead own, no cross-agent access
mainPrimary worktreeFull access
integIntegration worktreeRead-only across all agent worktrees

Cross-agent read denial is verified programmatically — an exec agent literally cannot see the verify agent's files. The WorktreeCreate hook auto-generates a sandbox profile (bubblewrap on Linux, Seatbelt on macOS) for each new worktree, ensuring isolation is enforced at the OS level, not just at the application level.

This matters because a compromised or misbehaving agent can't access credentials, modify another agent's work, or exfiltrate data from a neighboring worktree. The isolation is structural — built into the filesystem and enforced by the operating system's process sandbox.

Part Four

Quick Reference

16

Quick Reference Recipes

Start a New GSD Project with Git

mkdir my-project && cd my-project
git init
# open Claude Code with GSD installed
/gsd:new-project
git add . && git commit -m "chore: initialize project with GSD"

Save Your Work and Come Back Later

/gsd:pause-work       # creates handoff document
git add . && git commit -m "chore: pause work at phase 12 task 3"
# ... days later ...
/gsd:resume-work      # reads handoff, continues exactly where you left off

Work on Two Features Simultaneously with Worktrees

# Feature A in main directory
git checkout -b feature/auth

# Feature B in a separate worktree
git worktree add ../my-project-api feature/api-cache

# Work on either by cd-ing into the right directory
cd ~/projects/my-project/       # auth feature
cd ~/projects/my-project-api/   # api cache feature

# Each can run its own GSD session independently

Emergency Revert a Bad Phase

# Find the commit before the bad phase started
git log --oneline

# Revert all commits from the bad phase
git revert HEAD~5..HEAD    # reverts the last 5 commits

# Or, nuclear option: reset to before the phase (destroys history)
git reset --hard abc1234
# ⚠️ Only do this on your own branch, never on shared branches

Share a Repo on a Local Network

# Set up a bare repo on NFS
ssh nas "mkdir -p /share/git/project.git && cd /share/git/project.git && git init --bare"

# Each team member
git clone ssh://nas/share/git/project.git
# ... work, commit ...
git push origin feature/my-work
git pull origin main

The Daily Team Routine

# Morning: pull latest, update your branch
git checkout main && git pull
git checkout feature/my-work && git merge main

# Work: GSD executes, commits atomically
/gsd:resume-work

# End of day: push your branch
git push origin feature/my-work

# When feature is done: merge to dev, delete branch
git checkout dev && git merge feature/my-work
git push origin dev
git branch -d feature/my-work

Git Cheatsheet

TaskCommand
Create repogit init
Clone repogit clone <url>
See statusgit status
See historygit log --oneline
Stage filesgit add <files>
Commitgit commit -m "msg"
New branchgit checkout -b name
Switch branchgit checkout name
Mergegit merge branch
Pushgit push origin branch
Pullgit pull origin branch
Tag a releasegit tag -a v1.0.0 -m "msg"
List branchesgit branch
Delete branchgit branch -d name
Create worktreegit worktree add path branch
List worktreesgit worktree list
Abort mergegit merge --abort
See diffgit diff
Stash changesgit stash / git stash pop