Skip to content
Agentmart
Submit a tool

git-group-commit

Group uncommitted changes into feature commits with conventional messages, and emit runnable commit artifacts.

Skill by DimmKirr

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/dimmkirr-git-group-commit

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Group uncommitted changes into feature commits with conventional messages, and emit runnable commit artifacts. Use when the user asks to commit changes, write or improve a commit message, split work into multiple commits, or another skill needs commit messages for uncommitted changes. A single change is handled as one group. Do NOT use for PR descriptions (git-pr-message owns those).

Use cases: writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Node.js package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/git-group-commit

What's inside

Skill name
git-group-commit
Description
Group uncommitted changes into feature commits with conventional messages, and emit runnable commit artifacts. Use when the user asks to commit changes, write or improve a commit message, split work into multiple commits, or another skill needs commit messages for uncommitted changes. A single change is handled as one group. Do NOT use for PR descriptions (git-pr-message owns those).
License
MIT
Instructions
201 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Files (8)

  • SKILL.md
  • openai.yaml · agents/
  • evals.json · evals/
  • format.md · references/
  • codex-msg.sh · scripts/
  • group-commit.sh · scripts/
  • group-commit.test.bats · scripts/
  • workflow.js · scripts/

SKILL.md (first lines)

# Git Group Commit

Analyze uncommitted changes, group them by feature, generate a conventional commit message per group, and emit runnable commit artifacts inside the git dir (`$(git rev-parse --git-dir)/`, normally `.git/`) so they never pollute the working tree and can never be committed by accident:

- `commits.json` — the single source of truth: `{ groups: [...], excluded: [...] }` holding the full plan (files, descriptions, messages, exclusions)
- `group-commit.sh` — a static runner that reads `commits.json` and commits each group in sequence, wired to a repo-local git alias so it runs as `git group-commit`

A single logical change is not a special case — it produces one group and the same flow.

This skill never commits. The user reviews `commits.json` (the summary printed at the end is the human-readable view of it), then runs:

```bash
git group-commit
```

## Context (auto-injected on supported platforms)

!git diff HEAD
!git status
!git log --oneline -10

## Execution modes

**Fast path (single group — check this FIRST, any platform):** the auto-injected context above already contains the full diff. If everything uncommitted is clearly ONE logical change (every file serves the same goal — one group is the only sensible plan), do NOT invoke Workflow and do NOT delegate message generation: both would re-read a diff you have already paid for, and the plan/verify/assemble agents exist to arbitrate *between* groups. Instead execute inline:

- Steps 1–3 as written; steps 4–5 collapse (the single group is all uncommitted files minus exclusions; the standalone-build check is skipped for one group anyway)
- Step 6 as written; step 7 yourself — write the message directly from the diff already in context, following [references/format.md](references/format.md)
- Steps 8–9 as direct shell commands: write the plan to a temp file with a quoted heredoc, then `sh <skill dir>/scripts/group-commit.sh --install <plan>` (validates, stamps `diffHash`, installs runner + alias — mechanical, no agent), then step 10

If you are not sure it's one group, it isn't — use a mode below.

**Workflow mode (preferred for 2+ groups, Claude Code):** if the Workflow tool is available, do not execute steps 3–9 inline. Instead invoke, using this skill's base directory (announced when the skill loaded) as the script path:

```
Workflow({ scriptPath: "<skill base dir>/scripts/workflow.js",
           args: { stateKey: "<output of: git status --porcelain | git hash-object --stdin>" } })
```

Always pass `args.stateKey` (one cheap shell command) — it keys the plan agent's cache to the working-tree state, so resuming after commits or edits re-plans instead of replaying a stale cached plan. Optionally add `skillDir: "<skill base dir>"`; without it the script defaults to `~/.claude/skills/git-group-commit` and agents fall back to locating the folder.

The script owns model selection — planning and per-group message generation run on Sonnet (messages fan out in parallel, one agent per group), artifact assembly runs on Haiku — so the session model never burns tokens on this. When it completes, relay its returned summary (groups, headers, exclusions, next command) per step 10.

**Inline mode (fallback, Codex or Workflow unavailable, 2+ groups):** execute all steps below yourself, with one substitution — in step 7, do NOT write messages with the session model. (Exception: if planning lands on a single group after all, fall back to the fast path above — one delegated read of the full diff costs more than writing one message.) For each group run:

```bash
sh <skill dir>/scripts/codex-msg.sh <skill dir> <tmpfile> <group files...>
```

and read the message from `<tmpfile>`. The script delegates to `codex exec` with a pinned cheap model (`GROUP_COMMIT_MSG_MODEL`, default `gpt-5.1-codex-mini`), so message generation costs mini-model tokens even when the session runs a frontier model. Planning (steps 3–5) stays on the session model — grouping is the judgment-heavy part. If the `codex` CLI is unavailable, fall back to writing messages inline.

## Steps

1. **Gather state** (review auto-injected context above, or run manually if not available):
   - `git status` — all modified/untracked files
   - `git diff HEAD` — full uncommitted diff (staged + unstaged)
   - `git log --oneline -20` — recent commits to identify already-committed work
   - `git branch --show-current` — for ticket ID extraction (step 6)

2. **Check for remaining work**: If there are no uncommitted changes (no modified, no untracked files besides `CONTINUE.md`), print "All groups committed." and stop. Set `GIT_DIR=$(git rev-parse --git-dir)` — all artifacts below live there.

3. **Read or create `$GIT_DIR/commits.json`**:
   - If it exists, read it and remove any groups whose files are ALL already committed (cross-check against `git status` — if every file in a group is clean, that group is done). No renumbering needed — array position is the only ordering.
   - If it doesn't exist, or all groups in it are done, plan fresh from the current uncommitted changes.

4. **Identify feature groups** (only when creating fresh): Read the diff and cluster changes into groups a user would recognize as separate features. Each group should be independently committable. One group total is a normal outcome. Use these signals:
   - Files in the same package/directory working toward the same goal
   - A new capability end-to-end (config + implementation + tests + CLI wiring)
   - Infrastructure/nix/build changes that support a specific feature vs. standalone fixes
   - Cross-check against `git log` — if a group's files were already partially committed, note what remains

   Order groups by dependency — foundational changes first, CLI integration last. Give each
   group a short name and a 1-2 sentence description (both land in `commits.json`, step 8).

   **When a file is contested between two features, prefer including it over excluding it.**
   Pull in whatever the group needs to compile and pass its own tests, even if that means a
   bigger commit than the "pure" feature split. But bound it: if including a file drags in a
   transitive chain that swallows an unrelated feature wholesale, stop — split the *feature*
   across commits instead. A feature spanning two commits is fine; one commit swallowing the
   whole branch is not. Note in the group's `notes` field which part was deferred and why.

5. **Verify each group compiles standalone** (skip when there is only one group — nothing is being split). **Never touch the real index** — the user's staging (including `git add -p` splits) must survive planning. Work in a throwaway index, inside ONE shell invocation (env does not persist between tool calls):

   ```bash
   export GIT_INDEX_FILE=$(mktemp -u); git read-tree HEAD
   ```

   Then for each group in order:

   - `git add` the group's files **cumulatively** (no reset between groups) — the throwaway
     index now matches exactly what that group's commit will contain on top of the previous ones.
   - Extract the index and build it in isolation — the working tree hides missing
     dependencies, because uncommitted files from later groups are still on disk:

     ```bash
     S=$(mktemp -d); git archive "$(git write-tree)" | tar -x -C "$S"
     cp -r <any gitignored-but-required dirs> "$S/"   # e.g. generated docs/
     (cd "$S" && go build ./... && go test ./<changed pkgs>/...)
     ```

     If it fails, move the offending files into the group that defines their dependencies (or
     pull the dependency in, per the rule above), update the plan, and re-check. Compare
     any failure against the same build of plain `HEAD` before treating it as caused by this
     group — some failures are pre-existing.

   After the last group, `rm -f "$GIT_INDEX_FILE"`. The real index was never modified.

6. **Extract ticket IDs and fetch tickets once** (reused for every group's message):
   - From the branch name (e.g. `username/ABC-166-...` → `ABC-166`), existing commits on this branch, and `[ABC-xxx]` patterns in the diff
   - Fetch each from Linear / Jira MCP in parallel: `get_issue` with `includeRelations: true`; capture `identifier`, `title`, short `description`, `state.name`, and parent identifier/title if present
   - If no tickets are found, messages omit the `[ABC-xxx]` header

7. **Generate a message per group** — scoped strictly to that group's files:
   - Diff only the group: `git diff HEAD -- <group files>` (plus `git diff --no-index /dev/null <file>` for untracked files). Never generate a message from the full-tree diff.
   - Follow [references/format.md](references/format.md) exactly — it owns the message format, conventional commit rules, the initial-commit special case, and the user-impact quality check.
   - Only tag a group's header with ticket IDs whose work that group actually contains.

8. **Write the plan** — the single source of truth, installed as `$GIT_DIR/commits.json` in step 9. Write it to a temp file with a **quoted** heredoc (`<<'EOF'`, so nothing in messages is shell-expanded):

   ```json

From DimmKirr/skills, MIT.

More from DimmKirr/skills

Signals

Stars
0
Forks
0
Open issues
0
Last commit (this folder)
Oct 5, 2026 (24 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from DimmKirr

Cite this page

git-group-commit skill. Agent Mart. https://agentmart.dev/skills/dimmkirr-git-group-commit (last updated 2026-10-24)