Skip to content

Git Workflow

Branching conventions for this repository. All branches are created off main unless working within an initiative/ batch (see below).

Branch Prefixes

PrefixUseExample
feat/New content — provider profiles, frameworks, new directoriesfeat/add-moodle-profile
fix/Corrections — factual errors, stale data, broken links, typosfix/edunext-pricing-update
chore/Non-content maintenance — CLAUDE.md, skills config, symlinks, .gitignorechore/update-skills-symlinks
initiative/Long-running collection branch — see belowinitiative/q2-lms-competitive-refresh
local/Personal scratch work not intended for mergelocal/lms-competitive-deck

Naming convention: prefix/short-kebab-description

Keep descriptions short (3–5 words). Use the date or quarter suffix on initiative/ branches when the scope is time-boxed: initiative/competitor-analysis-q2-2026.


Initiative Branches

Use an initiative/ branch when multiple related PRs need to ship together as a coherent batch — before any of it goes to main.

main
└── initiative/scope-name          ← created off main
    ├── ← feat/sub-feature-a       (PR targets initiative/, not main)
    ├── ← feat/sub-feature-b
    └── ← fix/related-correction
         → final PR: initiative/scope-name → main

Workflow:

  1. Create initiative/your-scope off main
  2. Open individual feat/ or fix/ PRs — set the base branch to the initiative branch, not main
  3. Review and merge each PR into the initiative branch normally
  4. When the batch is complete and stable, open a single PR: initiative/scope-namemain

When to use initiative branches:

  • A new section of the knowledgebase being built across several sessions
  • A competitive analysis refresh touching multiple provider profiles and the overview
  • Any work where partial shipping would leave the repo in an inconsistent state

When to go direct to main:

  • A standalone feat/ or fix/ that is self-contained and doesn't depend on other in-flight work

Branch Lifecycle

  • Delete branches after their PR is merged — both locally and on the remote
  • local/ branches are exempt from this; they are personal and may persist indefinitely
  • Stale initiative/ branches that are abandoned should be deleted with a note in the PR or issue explaining why the work was dropped

Claude Session Startup

This is a mandatory gate. Do not create any branch or begin any content work until all four steps below are complete and the base branch is confirmed.

Before starting any work in a new session or worktree:

  1. Fetch latest remote state.

    bash
    git fetch --all --prune

    Run this first. Do not rely on the branch list that was present when the worktree was created.

  2. List remote initiative branches.

    bash
    git branch -r | grep initiative/
  3. Check for open or draft PRs from initiative branches targeting main.

    bash
    gh pr list --state open --base main --json headRefName,title,isDraft,url \
      | jq '.[] | select(.headRefName | startswith("initiative/"))'

    If jq is unavailable, run gh pr list --state open --base main and filter the output visually for initiative/ entries.

  4. Present findings to the user and confirm the base branch. After running steps 2–3, surface the results:

    • List any initiative/ branches that exist on the remote
    • List any of those with an open or draft PR targeting main (include title and URL)

    Then ask: "Should this work be based off one of these initiative branches, or off main directly?"

    Do not create any branch or begin any work until the user answers. If no initiative branches exist and no matching PRs are found, proceed off main without asking.

    Skipping this gate risks basing work on main when the correct baseline is an initiative branch, causing merge conflicts or rework against the wrong state.


Opening Pull Requests

Run through this checklist before opening any PR against a private Schema repository:

1. Rename the branch if it doesn't follow the naming convention

Check the current branch name against the prefix/short-kebab-description convention. If it was auto-generated (e.g., claude/cranky-darwin-1dc2d1) or otherwise doesn't match, rename it before opening the PR:

bash
git branch -m <current-name> <correct-name>
git push origin -u <correct-name>
git push origin --delete <current-name>   # remove the old remote branch

2. Sync against the latest remote target branch

Fetch and rebase (or verify no conflicts) against the current remote state of the target branch — whether main or an initiative/ branch:

bash
git fetch origin
git rebase origin/<target-branch>

This prevents the PR from opening with conflicts or against a stale base, which would require a second cleanup cycle.

3. Include Notion project context in the PR body

For any PR against a private Schema repository, include a Notion section in the PR description linking the work to its project:

markdown
## Notion
[Project Name](https://notion.so/...)
Task: [Task or sub-project name](https://notion.so/...) <!-- if applicable -->
  • Use the actual Notion project name as the link text.
  • Include a task-level link when the PR maps to a specific task or sub-project within the broader initiative.
  • If Claude does not know the Notion project for the current session or worktree, ask before opening the PR.
  • If the user confirms there is no linked project, use No specific project as the placeholder so the section is never silently missing:
markdown
## Notion
No specific project

Schema Education — Internal Research