mcpField
A
aep-git-ref

aep-git-ref

github.com/memorysaverDevelopment1858 installsUpdated 6w ago
Repository

About aep-git-ref

aep-git-ref is the Git and worktree conventions reference for AEP workflows, used by other skills and parallel development tasks. It centralizes integration-branch resolution, worktree handling, commits, pull requests, and recovery guidance.

Key features

  1. 01Resolve the integration branch
  2. 02Manage worktree lifecycles
  3. 03Define branch and commit conventions
  4. 04Document push and PR practices
  5. 05Provide Git recovery procedures

Use cases

  1. 01Create isolated workspaces for parallel agents
  2. 02Standardize feature-branch commits and merges
  3. 03Recover from worktree or commit loss

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/memorysaver/agentic-engineering-patterns --skill aep-git-ref

After installing, type/aep-git-refin Claude Code to confirm it loaded.

Details

From the project README

Git + Worktree Reference (AEP)

/aep-launch, /aep-build, and /aep-wrap operate on a plain git repository plus git worktree for parallel agent isolation — when these skills say "commit", they mean git commit. This skill is the canonical home for AEP's git conventions: every other skill resolves $BASE, creates/removes worktrees, and opens PRs by pointing here, never by re-inlining these blocks. Rationale for plain git (agent training data, universal tooling): docs/decisions/migrate-from-jj-to-git.md.


Integration Branch

Every AEP git operation targets the integration branch — the branch feature worktrees are created from, rebased onto, PR'd into, merged into, and where control-plane commits (/aep-dispatch, /aep-design, the /aep-wrap archive) land. Throughout this skill and the bash blocks in /aep-launch, /aep-build, /aep-wrap, and the product-context skills, this branch is referred to as $BASE.

AEP auto-detects one of two modes — no configuration required for the common cases:

ModeConditionIntegration ($BASE)Production
single-branch (default)no develop branchmainmain (same branch)
two-branchdevelop existsdevelop (staging)main (promote-only)

A project grows from single- to two-branch mode simply by creating a develop branch — no reconfiguration. In two-branch mode AEP never touches the production branch (main): promotion from integration to production (develop → main) is the user's concern, exactly like deployment, which is already outside AEP's scope.

Resolving $BASE

Every git-touching skill resolves the integration branch at the top of its first bash block:

# Resolve AEP integration branch ($BASE): override → auto-detect develop → main
BASE=$(git config --get aep.integration-branch 2>/dev/null || true)
if [ -z "$BASE" ]; then
  if git show-ref --verify --quiet refs/heads/develop \
     || git show-ref --verify --quiet refs/remotes/origin/develop; then
    BASE=develop
  else
    BASE=main
  fi
fi

Resolution order:

  1. Explicit override — git config --get aep.integration-branch. This is an override only, for a non-standard integration branch name (e.g. staging, integration). You do not set it for the standard main/develop cases — those are auto-detected. /aep-onboard reports the detected mode and only writes this key when you use a non-standard name (git config aep.integration-branch <name>; unset with git config --unset aep.integration-branch).
  2. Auto-detect — develop if it exists locally or on origin.
  3. Default — main (single-branch mode).

Because the standard cases are auto-detected (not pinned), a project grows from single- to two-branch mode with no reconfiguration: create develop and every skill resolves $BASE to it on the next run. (If you had pinned aep.integration-branch=main, that override would win and suppress the upgrade — which is why setup does not pin the default.)

git config --get aep.integration-branch is repo-local and shared across all worktrees via the common .git/config, so $BASE resolves identically in the main session and inside any .feature-workspaces/<name> worktree.


Worktree Lifecycle

Create
# Resolve $BASE first — see "Resolving $BASE" above
mkdir -p .feature-workspaces
git worktree add -b feat/<name> .feature-workspaces/<name> "$BASE"
  • Path is always under .feature-workspaces/<name> (kept gitignored).
  • Branch is always feat/<name> — corresponding to the OpenSpec change name or story id.
  • Base is always the integration branch $BASE.

The worktree shares .git/objects with the main repo, so creating it is fast and history is not duplicated. Only the working tree files are duplicated on disk.

Inspect
git worktree list                            # all worktrees, branches, paths
git -C .feature-workspaces/<name> status     # status inside a specific worktree
git -C .feature-workspaces/<name> log --oneline "$BASE"..HEAD   # commits unique to the feature branch
Remove (/aep-wrap step 6)
git worktree remove .feature-workspaces/<name>
git branch -d feat/<name>

If git branch -d warns the branch isn't fully merged (likely because the PR was squash-merged so commit SHAs differ), force with git branch -D feat/<name> after confirming via gh pr view <number> --json state that the PR is MERGED.

Recover from a corrupt worktree directory

If .feature-workspaces/<name>/ was deleted manually:

git worktree prune                           # forget the orphaned registration
git branch -D feat/<name>                    # delete the orphan branch (if needed)

If .git/worktrees/<name>/ still references a missing path (e.g. you moved the parent directory):

git worktree repair .feature-workspaces/<name>

Branch Naming

BranchPatternCreated by
Feature workfeat/<short-name>/aep-launch (one per story)
Migration / chorechore/<short-name>manually, when applicable
Hotfix off mainfix/<short-name>manually
Migration projectmigration/<topic>manually

Rules:

  • Use kebab-case after the slash. No spaces, no underscores.
  • Keep names short (≤ 30 chars) — they appear in tab labels, signal files, and PR titles.
  • Reuse a deleted branch name once its worktree is fully removed (git worktree prune clears the dangling refs).

The One-Commit-per-Task Pattern (Phase 4 of /aep-build)

What

tasks.md lists N tasks. The feature branch ends up with N commits — one per task — in the same order. Conventional-commit format. Workspace agents implement linearly, committing after each task, so the commit count matches the task count:

# Implement task 1
# ... edit files ...
git add -A
git commit -m "feat(auth): extract auth service"

# Implement task 2
# ... edit files ...
git add -A
git commit -m "feat(auth): add token refresh flow"

# ... etc.

After each commit, record the short SHA in .dev-workflow/feature-verification.json against the matching task entry's commit_sha field.

Why this shape
  • The PR's commit list reads like a table of contents matching tasks.md.
  • Each commit is a self-contained unit that the evaluator (in Phase 5) and reviewers (in Phase 11) can git show <sha> independently.
  • We squash-merge at PR-merge time, so per-commit hygiene only matters for review readability — the integration branch's history stays clean automatically.
  • It removes any need to rewrite history mid-stream, which is where agents most often go off the rails.
What to do when something goes wrong
SituationAction
Forgot a file in the just-committed taskgit add <file> && git commit --amend --no-edit (only safe before the next task's commit)
Realized the previous task is broken, several commits agoAdd a new commit: fix(<scope>): correct <issue from task N> — the history stays append-only
Review feedback or eval-loop FAILAdd a follow-up commit: fix(<scope>): address review on <topic>
Need to update against new origin/$BASEgit fetch origin && git rebase origin/"$BASE" && git push --force-with-lease origin feat/<name>
Conflicts during rebaseResolve in working tree, git add <files> && git rebase --continue. If hopelessly tangled, git rebase --abort and surface to the orchestrator via signal file.

Push a rewritten branch with --force-with-lease rather than a bare --force: the lease variant fails safely when someone else has pushed since your last fetch.


Publishing & PR Conventions

Push the feature branch
# First push (after Phase 9 cleanup):
git push -u origin feat/<name>

# Subsequent pushes (review fixes, rebases):
git push origin feat/<name>
# or after a rebase:
git push --force-with-lease origin feat/<name>
Open the PR — always set base explicitly
# $BASE is the integration branch — resolve it first (see "Integration Branch" above)
gh pr create --base "$BASE" --title "<title>" --body "<body>"

The --base "$BASE" flag is mandatory: without it gh infers the base from local branch state (a dispatch commit can look like a recent base), the PR merges into a non-integration branch, and the code never lands on $BASE. In two-branch mode an inferred base could be production main, which AEP never merges feature work into.

Merge the PR
gh pr merge <number> --squash --delete-branch

We always squash-merge. The feature branch's per-task commits collapse into one commit on the integration branch ($BASE), which keeps its log readable while preserving the per-task review trail in the PR's "Commits" tab.


Control-Plane Commits (on the integration branch)

/aep-design, /aep-dispatch, /aep-envision, /aep-map, /aep-calibrate, /aep-validate, /aep-reflect, and the /aep-wrap archive step all commit directly to the integration branch ($BASE). The pattern is identical:

# Resolve $BASE first — see "Resolving $BASE" above
git pull --ff-only origin "$BASE"       # fail-fast if the integration branch has diverged
git add <specific-files>                # never -A on the integration branch; be explicit
git commit -m "<conventional message>"
git push origin "$BASE"

The --ff-only is intentional — it refuses a non-fast-forward pull, which means concurrent pushes get caught instead of silently merged. If the pull fails because someone else pushed first, fetch, rebase your work, and try again.


Recovery

Lost a commit (committed to wrong branch, or amend'd away)
git reflog                              # find the orphaned commit's SHA
git cherry-pick <sha>                   # bring it onto the current branch
# or
git reset --hard <sha>                  # if you want to rewind to that point
Lost an entire branch (deleted with -D)
git reflog                              # the deleted branch's tip is in here
git branch <name> <sha>                 # recreate the branch at that tip
Lost work in a worktree directory you removed

If you ran rm -rf .feature-workspaces/<name> without committing first, the work is gone — git worktree only tracks committed history. .dev-workflow/ files (signals, lessons, progress) are also gone since they're gitignored. Use git worktree remove instead of rm -rf next time; it refuses if the worktree has uncommitted changes.

OpenSpec files missing after rebase

If the dispatch commit's OpenSpec files disappeared during a rebase or merge:

git log --oneline -n 30                 # find the dispatch commit SHA
git restore --source=<sha> -- openspec/

This restores openspec/ to the state of the dispatch commit without touching anything else.


Disk Budget

Each worktree adds approximately one full working-tree copy on disk. .git/objects is shared across all worktrees, so commit history isn't duplicated. For a typical AEP repo (~100 MB working tree, multi-GB .git/objects after years of history), three concurrent agents adds ~300 MB on top of one shared .git/.

Monitor with:

du -sh .feature-workspaces/             # working-tree footprint
du -sh .git/objects                     # shared history

If disk pressure hits before agents finish, prefer pausing new /aep-launch invocations over forcibly removing in-flight worktrees.


Cheat Sheet

You want to…Run
Create a feature worktreegit worktree add -b feat/<n> .feature-workspaces/<n> "$BASE"
List all worktreesgit worktree list
See feature-branch commitsgit log --oneline "$BASE"..HEAD
Sync against latest $BASEgit fetch origin && git rebase origin/"$BASE"
Push after rebasegit push --force-with-lease origin feat/<n>
Open PRgh pr create --base "$BASE"
Merge PRgh pr merge <#> --squash --delete-branch
Remove worktree post-mergegit worktree remove .feature-workspaces/<n> && git branch -d feat/<n>
Recover deleted commitgit reflog then git cherry-pick <sha>
Restore lost openspec/ filesgit restore --source=<sha> -- openspec/

Comments

Markdown supported