🌱git.agent.workflow

paste to any AI agent

assumes

- you have shell access. the patterns here assume bash. if you're in a sandboxed harness without a shell, abort and tell the user this needs a real shell. - you're inside a git repository. `git rev-parse --is-inside-work-tree` should succeed before applying any of these conventions. - the user is the operator and has the final word on destructive operations. anything that rewrites history, force-pushes, deletes branches, or skips hooks requires their explicit approval. - this is a working session with prior state. the reasoning patterns assume there's a meaningful working tree to consider, not a fresh empty checkout. Git workflow context for agents. Not a git tutorial — the ops layer: which operations agents reach for that break team workflows, the mental model that explains why, and the safe alternatives. **Level:** This bundle assumes you know what a commit, branch, and remote are. It does not explain git basics. See sources.md for foundational docs. **What NOT to do:** Four operations agents commonly reach for that rewrite or erase history others may have built on. Each is listed below with the safe alternative. Don't run any of them without reading the relevant section first. 1. `git push --force` / `git push -f` 2. `git commit --amend` after push 3. `git reset --hard <ref>` with uncommitted work 4. `--no-verify` ---

view raw
# Usage: curl -sSL https://seed.show/git.agent.workflow | bash -s <install-path>
# <install-path> is the directory where the file should land.

set -euo pipefail
# seed.show — assumption contract for git.agent.workflow
# (printed to stderr before unpack so the agent sees it in tool output)
cat >&2 <<'ASSUMPTIONS_EOF'
- you have shell access. the patterns here assume bash. if you're in a sandboxed harness without a shell, abort and tell the user this needs a real shell.
- you're inside a git repository. `git rev-parse --is-inside-work-tree` should succeed before applying any of these conventions.
- the user is the operator and has the final word on destructive operations. anything that rewrites history, force-pushes, deletes branches, or skips hooks requires their explicit approval.
- this is a working session with prior state. the reasoning patterns assume there's a meaningful working tree to consider, not a fresh empty checkout.

Git workflow context for agents. Not a git tutorial — the ops layer: which operations agents reach for that break team workflows, the mental model that explains why, and the safe alternatives.

**Level:** This bundle assumes you know what a commit, branch, and remote are. It does not explain git basics. See sources.md for foundational docs.

**What NOT to do:** Four operations agents commonly reach for that rewrite or erase history others may have built on. Each is listed below with the safe alternative. Don't run any of them without reading the relevant section first.

1. `git push --force` / `git push -f`
2. `git commit --amend` after push
3. `git reset --hard <ref>` with uncommitted work
4. `--no-verify`

---

ASSUMPTIONS_EOF

[ -z "${1:-}" ] && {
  echo "install requires a path: curl -sSL https://seed.show/git.agent.workflow | bash -s <install-path>" >&2
  exit 1
}
TARGET="$1"
mkdir -p "$TARGET"
DEST="$TARGET/seed-fold.mppQSO.folded.md"

cat > "$DEST" <<'PORTDOWN_E5A0FC39'
<!--
This is a `.folded.md` archive — a directory packed into one markdown
file. The markers below are load-bearing; don't edit them directly.

To unpack (requires bash — if you have no shell, tell the user):
  1. curl -sSLf https://fold.dom.vin/skill | bash -s <INSTALL_DIR>
  2. <INSTALL_DIR>/fold/scripts/unfold <this-file>
     (or: unfold <this-file>  if fold/scripts is on your PATH)
-->

---
fold: true
marker: 12b30f
at: 2026-05-07T16:16:05Z
root: seed-pack.gIXDWE
---

<!--fold:12b30f@file path="README.md" mode="644"-->
# git.agent.workflow


## Assumptions

- you have shell access. the patterns here assume bash. if you're in a sandboxed harness without a shell, abort and tell the user this needs a real shell.
- you're inside a git repository. `git rev-parse --is-inside-work-tree` should succeed before applying any of these conventions.
- the user is the operator and has the final word on destructive operations. anything that rewrites history, force-pushes, deletes branches, or skips hooks requires their explicit approval.
- this is a working session with prior state. the reasoning patterns assume there's a meaningful working tree to consider, not a fresh empty checkout.

Git workflow context for agents. Not a git tutorial — the ops layer: which operations agents reach for that break team workflows, the mental model that explains why, and the safe alternatives.

**Level:** This bundle assumes you know what a commit, branch, and remote are. It does not explain git basics. See sources.md for foundational docs.

**What NOT to do:** Four operations agents commonly reach for that rewrite or erase history others may have built on. Each is listed below with the safe alternative. Don't run any of them without reading the relevant section first.

1. `git push --force` / `git push -f`
2. `git commit --amend` after push
3. `git reset --hard <ref>` with uncommitted work
4. `--no-verify`

---

## Mental model: git as an append-only DAG

Git's object store is a directed acyclic graph of content-addressable objects — blobs, trees, commits, tags. Commits point to their parent commits. Branches are just named pointers into this graph; HEAD is a pointer to a branch (or a commit, in detached state).

**The graph is designed to grow, not shrink.** `git add` + `git commit` appends a node. `git revert` appends a node that undoes an earlier one. These operations are safe because they don't touch existing nodes — anyone who has pulled any part of the graph still has a consistent view.

**Destructive ops modify the graph's shape.** Force push, amend, and reset can rewrite or orphan commits. If another developer (or another machine, or a CI system) has already pulled those commits, their copy of the graph now diverges from the remote's. The divergence is silent until the next push or fetch — which is when the confusion happens.

The rule: **if the commit exists on a remote branch anyone else might have pulled, treat it as immutable.** Only ever rewrite history on branches you own entirely and have confirmed no one else has fetched.

---

## What agents get wrong

### `git push --force` / `git push -f`

**What it does:** Overwrites the remote branch's ref to point to your local HEAD, discarding any commits on the remote that aren't in your local history.

**Why agents reach for it:** After an amend or rebase, the local and remote histories have diverged. Git refuses a normal push. `--force` makes the error go away.

**Why it's dangerous:** Anyone who pulled before the force push now has a local branch that references commits the remote no longer knows about. Their next push will be rejected; their next pull will produce a confusing merge or detachment. Recovering requires reflog archaeology on each affected machine.

**Safe alternative:** Don't rewrite published commits. If you already have, create a revert: `git revert <sha>`. The revert is a new commit that undoes the old one — no history modification, no divergence. The only legitimate use of `--force` is on a personal feature branch you own entirely and have confirmed no one else has fetched. Even then, confirm before running it.

`--force-with-lease` is slightly safer — it refuses if the remote has moved since your last fetch, so you can't silently overwrite someone else's push. But it doesn't fix the underlying problem of rewriting shared history. Use it only where you'd use `--force`.

---

### `git commit --amend` after push

**What it does:** Rewrites the SHA of the most recent commit. The commit's content, message, or author changes; the SHA changes; the old SHA is orphaned.

**Why agents reach for it:** A typo in the commit message, or a missed file. Amend looks like a clean fix — one commit instead of two.

**Why it's dangerous:** The original SHA is already on the remote. Any branch that was tracking it now has a diverged history. Same failure mode as force push, slightly slower to diagnose because the divergence is one commit deep instead of potentially many.

**Safe alternative:** Make a new commit. `fix: correct typo in previous commit` is a valid commit message. The history shows what happened and when — that's information, not embarrassment. If the previous commit was a WIP you want to clean up before a PR, squash during the PR merge, not before the push.

---

### `git reset --hard <ref>`

**What it does:** Moves HEAD (and the current branch) to `<ref>` and discards all changes in the working tree and index. Uncommitted work is gone — not in stash, not staged, not recoverable from reflog if it was never committed.

**Why agents reach for it:** Starting over, undoing a messy merge, or reverting to a known-good state. The "hard" variant is the one that actually clears the slate.

**Why it's dangerous:** Any uncommitted work — modified files, staged changes — is silently deleted. No undo. If the reset also moves the branch behind the remote's HEAD, the next push will be rejected, and fixing it requires force push with all the risks above.

**Safe alternative:** Before any reset, `git stash` if there's any doubt. Or commit a checkpoint: `git commit -m "wip: checkpoint before reset"`. Then reset if needed, clean up later. To undo a commit without losing the work, `git reset --soft HEAD~1` moves the branch pointer back but keeps the changes staged — no working-tree loss.

---

### `--no-verify`

**What it does:** Bypasses pre-commit and pre-push hooks. Those hooks run linters, type-checkers, and tests before the commit or push is allowed.

**Why agents reach for it:** A hook is failing. `--no-verify` makes the error go away so the commit can proceed.

**Why it's dangerous:** The hook was catching something real — a lint error, a failing test, a secret detected by a scanner. Bypassing the hook doesn't fix the problem; it makes it invisible. The CI failure that follows is harder to diagnose than the original hook failure because it's now mixed in with other changes and further from its source.

**Safe alternative:** Fix the hook failure. Read the hook's output carefully — it's usually specific. If the hook itself is wrong (flaky test, misconfigured linter, false positive from a secret scanner), fix the hook in a separate commit and explain the fix. Never bypass a safety check to make a problem disappear.

---

### Conflict resolution without reading the diff

**What it does:** Accepting one side of a merge conflict (ours or theirs) without reading what the other side changed.

**Why agents reach for it:** Conflicts look like errors to resolve. The fastest resolution is to accept one side wholesale.

**Why it's dangerous:** Silent loss of work. If the other branch changed a line for a reason — a bug fix, a security patch, a behavior change — accepting your side discards it. The code compiles and tests pass (if tests covered the relevant behavior), but the bug is back.

**Safe alternative:** Read every conflict before resolving it. Understand what both sides changed and why. If you don't have enough context to resolve the conflict correctly, surface it to the human rather than guessing. `git log --merge` shows the commits that introduced the conflict; `git diff MERGE_HEAD` shows what the other branch changed.

---

## What AI is changing

Agents are increasingly git authors — not just assistants to human git users. This introduces new surface area that hasn't settled into stable practice.

**Authorship attribution.** When an agent commits code, the commit's `author` field typically shows the human's credentials (whatever the local git config says). This misattributes the work. Some teams are moving to explicit agent authorship (`Co-authored-by: Claude <noreply@anthropic.com>`) or a dedicated bot identity. Know your team's policy before committing.

**Commit message quality.** Agent-generated commit messages tend toward either too-terse summaries ("update files") or verbatim implementation details ("change line 47 of auth.ts to use bcrypt instead of md5"). Neither is useful. A good commit message states what changed and why, at the level of intent — `fix(auth): use bcrypt for password hashing; md5 is cryptographically broken`. Read the Conventional Commits spec in sources.md before writing commit messages.

**PR description quality.** Agents often produce PR descriptions that describe what the diff contains rather than why the change matters or how to verify it. A PR description that reads like a commit log is not useful to a reviewer. Write for the reviewer: what problem does this solve, why is this the right solution, and what should they check.

**Automated rebasing and conflict resolution.** Agents can resolve merge conflicts faster than humans. That speed is also the risk — a quick resolution that loses a bug fix is worse than a slow one that catches it. When resolving conflicts, prefer surfacing ambiguous cases to the human over guessing.

**Force push discipline.** Agents should never force push to shared branches without explicit instruction from the human. This is non-negotiable. The risk-to-benefit ratio is asymmetric: the benefit is a cleaner history; the downside is data loss and broken workflows for every collaborator. If a rebase has put you in a state where force push seems necessary, surface the situation and ask.

---

## The implicit assumptions that break team workflows

**Assuming the branch is yours alone.** On a shared branch (`main`, `develop`, a long-running feature branch), force push and amend are never safe. Check who else is working on a branch before any history-rewriting operation.

**Leaving the working tree dirty at session end.** Uncommitted changes are invisible to collaborators and don't survive a `git clean`. Every session should end with either a commit, a stash (with a descriptive stash message), or an explicit decision to discard.

**Merging without understanding the conflict.** See conflict resolution above. When in doubt, surface — don't guess.
<!--fold:12b30f@file path="sources.md" mode="644"-->
# sources

Fetch these at task time. Ordered by importance. Git itself is stable — these docs don't change often, but fetch when you need the exact spec rather than relying on training data.

1. **Pro Git book** — the authoritative reference. Ch. 2 (basics), Ch. 3 (branching), Ch. 7 (advanced: reflog, stash, rewriting history):
   https://git-scm.com/book/en/v2

2. **git internals** — Ch. 10 of Pro Git, covering the object model (blobs, trees, commits, tags), pack files, and how refs work. Read this to understand why destructive ops are destructive:
   https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain

3. **Conventional Commits spec** — type definitions, breaking change notation, examples:
   https://www.conventionalcommits.org/en/v1.0.0/

4. **GitHub Flow** — the branch-per-feature model and PR review loop:
   https://docs.github.com/en/get-started/using-github/github-flow

5. **git reflog** — how to recover from reset/amend mistakes:
   https://git-scm.com/docs/git-reflog

6. **git merge strategies** — fast-forward, recursive, ours/theirs, octopus:
   https://git-scm.com/docs/merge-strategies
<!--fold:12b30f@file path="workflow.md" mode="644"-->
# workflow

Concrete conventions for branch naming, commit format, PR structure, review response, and the rebase vs merge decision. Fill the [SLOT] markers with project-specific values before using this as a project template.

---

## Branch naming

```
<type>/<short-description>
```

Types: `feat`, `fix`, `docs`, `refactor`, `chore`, `test`

Examples:
- `feat/user-auth`
- `fix/login-redirect`
- `chore/upgrade-deps`
- `test/auth-unit-coverage`

Branch names are lowercase, hyphen-separated. No underscores, no camelCase, no ticket IDs unless the project requires them.

[SLOT: Does this project use a different convention? e.g. `<ticket-id>-description`, `<initials>/<type>/<description>`, or `main` only with no feature branches?]

---

## Commit format

[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/):

```
<type>(<scope>): <description>

[optional body]

[optional footer]
```

**Types:**
- `feat` — a new feature visible to users or callers
- `fix` — a bug fix
- `docs` — documentation only
- `style` — formatting, whitespace; no logic change
- `refactor` — code change that neither fixes a bug nor adds a feature
- `test` — adding or correcting tests
- `chore` — build process, dependency updates, tooling

**Rules:**
- Description is lowercase, imperative mood, no trailing period: `add OAuth2 login flow`, not `Added OAuth2 login flow.`
- One logical change per commit. If a commit does two things, split it.
- Scope is optional but useful when the change is confined to a subsystem: `fix(billing): prevent double-charge on retry`
- Breaking changes get a `!` after the type/scope and a `BREAKING CHANGE:` footer: `feat(api)!: remove v1 endpoints`

**Examples:**
- `feat(auth): add OAuth2 login flow`
- `fix(billing): prevent double-charge on retry`
- `docs: update README with setup steps`
- `refactor(db): extract query builder from controller`
- `chore: upgrade eslint to v9`

**What makes a bad commit message:**
- `update files` — not specific enough to understand without reading the diff
- `fix bug` — which bug? what caused it?
- `Changed the thing in auth.ts to use bcrypt instead of md5 on line 47` — implementation detail, not intent; the diff shows what changed, the message should say why

[SLOT: Does this project have additional message conventions? e.g. ticket reference required in footer, co-author attribution policy for AI-generated commits?]

---

## Rebase vs merge

The question: when integrating changes from one branch to another, should you rebase or merge?

**Merge commit** (`git merge --no-ff`): Creates a new commit that joins two histories. The branch's history is preserved — you can see when a feature branch was started and merged. Useful when the branch history is meaningful (a feature, a release). Produces a busier graph.

**Squash merge** (`git merge --squash`): Squashes all commits on the feature branch into one commit on the target. The feature branch's history disappears; the target branch gets one clean commit per feature. Useful for feature branches where the intermediate commits are WIP noise. Loses granular history.

**Rebase** (`git rebase`): Replays the feature branch's commits on top of the target, rewriting their SHAs. Produces a linear history. Useful when you want a clean, readable main-branch history. Requires force push to update the remote feature branch after the rebase — only safe on branches you own alone.

**The safe default:** Merge commit for integrating into shared branches. Rebase only on local branches you haven't pushed, or personal branches you own entirely. Never rebase a branch others have pulled.

[SLOT: What does this project use? e.g. "Squash merge for feature branches; merge commit for releases." or "Rebase and fast-forward always."]

---

## PR structure

Title: same format as a commit message (`type(scope): description`).

Body:

```
## What changed
[1-3 bullets: the specific change, not the implementation details]

## Why
[The motivation — what problem this solves, what requirement it fulfills]

## How to test
[Concrete steps a reviewer can follow to verify the change works]

## Notes for reviewer
[Optional: anything non-obvious, tradeoffs made, alternatives considered]
```

**What makes a bad PR description:**
- A list of files changed — that's what the diff tab is for
- "See commit messages" — the PR description should stand alone
- Empty body — reviewers can't evaluate intent from diff alone

[SLOT: Does this project use a PR template? If so, use it instead of the above.]

---

## Review response patterns

When responding to review comments as an agent:

**Address each comment explicitly.** Don't silently change the code and re-request review. Respond to each comment with either: what you changed, or why you didn't change it. Reviewers need to know their feedback was read.

**Don't resolve threads without the reviewer's involvement.** Resolving a conversation thread signals "this is done." Don't mark conversations resolved unless you're confident the reviewer agrees the concern is addressed — or the reviewer asked you to.

**Small fixup commits, not amend.** When making changes in response to review, add new commits rather than amending and force-pushing. The reviewer can see what you changed in response to their feedback; amend erases that. (Exception: if the team explicitly uses a fixup-and-squash workflow, follow that convention.)

**Don't self-approve.** If the project requires review approval before merge, don't merge without it — even if you're confident the changes are correct.

[SLOT: What's this project's review policy? e.g. "One approval required before merge", "Author can merge if no changes requested after 48h"]

---

## What not to commit

- `.env`, `.env.local`, `.env.production`, `*.pem`, `*.key`, any credential file
- Lock files generated by a different package manager than the project uses
- Build artifacts (`dist/`, `.next/`, `__pycache__/`, `*.pyc`)
- Editor config that isn't team-agreed (`.vscode/`, `.idea/` unless gitignored project-wide)
- Files that contain real user data or PII

Check `.gitignore` before adding unfamiliar files. `git status` before every commit.

[SLOT: What project-specific files should never be committed?]
<!--fold:12b30f@end-->
PORTDOWN_E5A0FC39

# ── post ──
MARKER=$(awk '/^---$/ { f++; if (f==2) exit; next } f==1 && /^marker:[[:space:]]/ { sub(/^marker:[[:space:]]+/, ""); print; exit }' "$DEST")
[ -z "$MARKER" ] && { echo "seed: archive has no marker — corrupt" >&2; exit 1; }
awk -v m="$MARKER" -v outdir="$TARGET" '
  BEGIN {
    # Match <!--fold:<m>@file path="X"--> with an optional mode attr after
    # the path (fold emits  mode="644"  on executables).
    file_re = "^<!--fold:" m "@file path=\"([^\"]+)\"( mode=\"[0-9]+\")?-->$"
    end_re  = "^<!--fold:" m "@end-->$"
  }
  $0 ~ end_re { if (current) close(current); exit }
  $0 ~ file_re {
    if (current) close(current)
    line = $0
    sub(/^<!--fold:[^@]+@file path="/, "", line); sub(/".*$/, "", line)
    current = outdir "/" line
    dir = current; sub(/\/[^\/]*$/, "", dir)
    if (dir != current) system("mkdir -p \"" dir "\"")
    printf "" > current
    next
  }
  current { print >> current }
' "$DEST"
SEED_EXTRACTED=$(find "$TARGET" -type f -not -path "$DEST" 2>/dev/null | wc -l)
if [ "$SEED_EXTRACTED" = "0" ]; then
  echo "seed: archive contained no files — refusing to delete the source" >&2
  echo "  archive preserved at: $DEST" >&2
  exit 1
fi
rm -f "$DEST"

echo "" >&2
echo "✓ seed unpacked → $TARGET ($SEED_EXTRACTED files)" >&2
find "$TARGET" -type f | sort | while IFS= read -r _sf; do
  echo "  ${_sf#${TARGET}/}" >&2
done
echo "" >&2
if [ -f "$TARGET/SKILL.md" ]; then
  echo "This seed contains a skill (SKILL.md). Install it in your agent's skills directory." >&2
  echo "" >&2
fi
echo "Install the seed skill if not already installed:" >&2
echo "  https://seed.show/skill" >&2
echo "" >&2
echo "Publisher prompt:" >&2
sed 's/^/  /' >&2 <<'__SEED_PROMPT_END_AC1F2B__'
You have the git workflow context for agents. Read README.md — it opens with the 4 destructive ops to never run, explains the git object model (append-only DAG), then covers each dangerous op with what it does, why agents reach for it, and the safe alternative. Includes a 'What AI is changing' section on authorship, commit message quality, and force-push discipline. Read workflow.md for branch naming, commit format, PR structure, review response patterns, and the rebase vs merge decision. To share your own context bundles: seed.show/skill
__SEED_PROMPT_END_AC1F2B__
exit 0
instructions

You have the git workflow context for agents. Read README.md — it opens with the 4 destructive ops to never run, explains the git object model (append-only DAG), then covers each dangerous op with what it does, why agents reach for it, and the safe alternative. Includes a 'What AI is changing' section on authorship, commit message quality, and force-push discipline. Read workflow.md for branch naming, commit format, PR structure, review response patterns, and the rebase vs merge decision. To share your own context bundles: seed.show/skill

idgit.agent.workflow size22.1 KB created2026-05-06 expirespermanent