-
Notifications
You must be signed in to change notification settings - Fork 7.4k
feat: Git extension stage 1 — bundled extensions/git with hooks on all core commands
#1941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Copilot
wants to merge
6
commits into
main
Choose a base branch
from
copilot/extract-git-branching-operations
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
a084d09
feat: add git extension with hooks on all core commands
mnriem 2a6b79f
fix: set git identity env vars in extension tests for CI runners
mnriem 9166afe
fix: address PR review comments
mnriem 174e909
fix: address second round of PR review comments
mnriem 7fd87f9
fix: address third round of PR review comments
mnriem 995b255
fix: address fourth round of PR review comments
mnriem File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # Git Branching Workflow Extension | ||
|
|
||
| Git repository initialization, feature branch creation, numbering (sequential/timestamp), validation, remote detection, and auto-commit for Spec Kit. | ||
|
|
||
| ## Overview | ||
|
|
||
| This extension provides Git operations as an optional, self-contained module. It manages: | ||
|
|
||
| - **Repository initialization** with configurable commit messages | ||
| - **Feature branch creation** with sequential (`001-feature-name`) or timestamp (`20260319-143022-feature-name`) numbering | ||
| - **Branch validation** to ensure branches follow naming conventions | ||
| - **Git remote detection** for GitHub integration (e.g., issue creation) | ||
| - **Auto-commit** after core commands (configurable per-command with custom messages) | ||
|
|
||
| ## Commands | ||
|
|
||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `speckit.git.initialize` | Initialize a Git repository with a configurable commit message | | ||
| | `speckit.git.feature` | Create a feature branch with sequential or timestamp numbering | | ||
| | `speckit.git.validate` | Validate current branch follows feature branch naming conventions | | ||
| | `speckit.git.remote` | Detect Git remote URL for GitHub integration | | ||
| | `speckit.git.commit` | Auto-commit changes (configurable per-command enable/disable and messages) | | ||
|
|
||
| ## Hooks | ||
|
|
||
| | Event | Command | Optional | Description | | ||
| |-------|---------|----------|-------------| | ||
| | `before_constitution` | `speckit.git.initialize` | No | Init git repo before constitution | | ||
| | `before_specify` | `speckit.git.feature` | No | Create feature branch before specification | | ||
| | `before_clarify` | `speckit.git.commit` | Yes | Commit outstanding changes before clarification | | ||
| | `before_plan` | `speckit.git.commit` | Yes | Commit outstanding changes before planning | | ||
| | `before_tasks` | `speckit.git.commit` | Yes | Commit outstanding changes before task generation | | ||
| | `before_implement` | `speckit.git.commit` | Yes | Commit outstanding changes before implementation | | ||
| | `before_checklist` | `speckit.git.commit` | Yes | Commit outstanding changes before checklist | | ||
| | `before_analyze` | `speckit.git.commit` | Yes | Commit outstanding changes before analysis | | ||
| | `before_taskstoissues` | `speckit.git.commit` | Yes | Commit outstanding changes before issue sync | | ||
| | `after_constitution` | `speckit.git.commit` | Yes | Auto-commit after constitution update | | ||
| | `after_specify` | `speckit.git.commit` | Yes | Auto-commit after specification | | ||
| | `after_clarify` | `speckit.git.commit` | Yes | Auto-commit after clarification | | ||
| | `after_plan` | `speckit.git.commit` | Yes | Auto-commit after planning | | ||
| | `after_tasks` | `speckit.git.commit` | Yes | Auto-commit after task generation | | ||
| | `after_implement` | `speckit.git.commit` | Yes | Auto-commit after implementation | | ||
| | `after_checklist` | `speckit.git.commit` | Yes | Auto-commit after checklist | | ||
| | `after_analyze` | `speckit.git.commit` | Yes | Auto-commit after analysis | | ||
| | `after_taskstoissues` | `speckit.git.commit` | Yes | Auto-commit after issue sync | | ||
|
Comment on lines
+17
to
+46
|
||
|
|
||
mnriem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ## Configuration | ||
|
|
||
| Configuration is stored in `.specify/extensions/git/git-config.yml`: | ||
|
|
||
| ```yaml | ||
| # Branch numbering strategy: "sequential" or "timestamp" | ||
| branch_numbering: sequential | ||
|
|
||
| # Custom commit message for git init | ||
| init_commit_message: "[Spec Kit] Initial commit" | ||
|
|
||
| # Auto-commit per command (all disabled by default) | ||
| auto_commit: | ||
| default: false | ||
| after_specify: | ||
| enabled: true | ||
| message: "[Spec Kit] Add specification" | ||
| ``` | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| # Install the bundled git extension (no network required) | ||
| specify extension add git | ||
| ``` | ||
|
|
||
| ## Disabling | ||
|
|
||
| ```bash | ||
| # Disable the git extension (spec creation continues without branching) | ||
| specify extension disable git | ||
|
|
||
| # Re-enable it | ||
| specify extension enable git | ||
| ``` | ||
|
|
||
| ## Graceful Degradation | ||
|
|
||
| When Git is not installed or the directory is not a Git repository: | ||
| - Spec directories are still created under `specs/` | ||
| - Branch creation is skipped with a warning | ||
| - Branch validation is skipped with a warning | ||
| - Remote detection returns empty results | ||
|
|
||
| ## Scripts | ||
|
|
||
| The extension bundles cross-platform scripts: | ||
|
|
||
| - `scripts/bash/create-new-feature.sh` — Bash implementation | ||
| - `scripts/bash/git-common.sh` — Shared Git utilities (Bash) | ||
| - `scripts/powershell/create-new-feature.ps1` — PowerShell implementation | ||
| - `scripts/powershell/git-common.ps1` — Shared Git utilities (PowerShell) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| --- | ||
| description: "Auto-commit changes after a Spec Kit command completes" | ||
| --- | ||
|
|
||
| # Auto-Commit Changes | ||
|
|
||
| Automatically stage and commit all changes after a Spec Kit command completes. | ||
|
|
||
| ## Behavior | ||
|
|
||
| This command is invoked as a hook after (or before) core commands. It: | ||
|
|
||
| 1. Determines the event name from the hook context (e.g., if invoked as an `after_specify` hook, the event is `after_specify`; if `before_plan`, the event is `before_plan`) | ||
| 2. Checks `.specify/extensions/git/git-config.yml` for the `auto_commit` section | ||
| 3. Looks up the specific event key to see if auto-commit is enabled | ||
| 4. Falls back to `auto_commit.default` if no event-specific key exists | ||
| 5. Uses the per-command `message` if configured, otherwise a default message | ||
| 6. If enabled and there are uncommitted changes, runs `git add .` + `git commit` | ||
|
|
||
| ## Execution | ||
|
|
||
| Determine the event name from the hook that triggered this command, then run the script: | ||
|
|
||
| - **Bash**: `.specify/extensions/git/scripts/bash/auto-commit.sh <event_name>` | ||
| - **PowerShell**: `.specify/extensions/git/scripts/powershell/auto-commit.ps1 <event_name>` | ||
|
|
||
| Replace `<event_name>` with the actual hook event (e.g., `after_specify`, `before_plan`, `after_implement`). | ||
|
|
||
| ## Configuration | ||
|
|
||
| In `.specify/extensions/git/git-config.yml`: | ||
|
|
||
| ```yaml | ||
| auto_commit: | ||
| default: false # Global toggle — set true to enable for all commands | ||
| after_specify: | ||
| enabled: true # Override per-command | ||
| message: "[Spec Kit] Add specification" | ||
| after_plan: | ||
| enabled: false | ||
| message: "[Spec Kit] Add implementation plan" | ||
| ``` | ||
|
|
||
| ## Graceful Degradation | ||
|
|
||
| - If Git is not available or the current directory is not a repository: skips with a warning | ||
| - If no config file exists: skips (disabled by default) | ||
| - If no changes to commit: skips with a message |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| --- | ||
| description: "Create a feature branch with sequential or timestamp numbering" | ||
| --- | ||
|
|
||
| # Create Feature Branch | ||
|
|
||
| Create a new feature branch for the given specification. | ||
|
|
||
| ## User Input | ||
|
|
||
| ```text | ||
| $ARGUMENTS | ||
| ``` | ||
|
|
||
| You **MUST** consider the user input before proceeding (if not empty). | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Verify Git is available by running `git rev-parse --is-inside-work-tree 2>/dev/null` | ||
| - If Git is not available, warn the user and skip branch creation (spec directory will still be created) | ||
|
|
||
| ## Branch Numbering Mode | ||
|
|
||
| Determine the branch numbering strategy by checking configuration in this order: | ||
|
|
||
| 1. Check `.specify/extensions/git/git-config.yml` for `branch_numbering` value | ||
| 2. Check `.specify/init-options.json` for `branch_numbering` value (backward compatibility) | ||
| 3. Default to `sequential` if neither exists | ||
|
|
||
| ## Execution | ||
|
|
||
| Generate a concise short name (2-4 words) for the branch: | ||
| - Analyze the feature description and extract the most meaningful keywords | ||
| - Use action-noun format when possible (e.g., "add-user-auth", "fix-payment-bug") | ||
| - Preserve technical terms and acronyms (OAuth2, API, JWT, etc.) | ||
|
|
||
| Run the appropriate script based on your platform: | ||
|
|
||
| - **Bash**: `.specify/extensions/git/scripts/bash/create-new-feature.sh --json --short-name "<short-name>" "<feature description>"` | ||
| - **Bash (timestamp)**: `.specify/extensions/git/scripts/bash/create-new-feature.sh --json --timestamp --short-name "<short-name>" "<feature description>"` | ||
| - **PowerShell**: `.specify/extensions/git/scripts/powershell/create-new-feature.ps1 -Json -ShortName "<short-name>" "<feature description>"` | ||
| - **PowerShell (timestamp)**: `.specify/extensions/git/scripts/powershell/create-new-feature.ps1 -Json -Timestamp -ShortName "<short-name>" "<feature description>"` | ||
|
|
||
| **IMPORTANT**: | ||
| - Do NOT pass `--number` — the script determines the correct next number automatically | ||
| - Always include the JSON flag (`--json` for Bash, `-Json` for PowerShell) so the output can be parsed reliably | ||
| - You must only ever run this script once per feature | ||
| - The JSON output will contain BRANCH_NAME and SPEC_FILE paths | ||
|
|
||
| If the extension scripts are not found at the `.specify/extensions/git/` path, fall back to: | ||
| - **Bash**: `scripts/bash/create-new-feature.sh` | ||
| - **PowerShell**: `scripts/powershell/create-new-feature.ps1` | ||
|
|
||
| ## Graceful Degradation | ||
|
|
||
| If Git is not installed or the current directory is not a Git repository: | ||
| - The script will still create the spec directory under `specs/` | ||
| - A warning will be printed: `[specify] Warning: Git repository not detected; skipped branch creation` | ||
| - The workflow continues normally without branch creation | ||
|
|
||
| ## Output | ||
|
|
||
| The script outputs JSON with: | ||
| - `BRANCH_NAME`: The created branch name (e.g., `003-user-auth` or `20260319-143022-user-auth`) | ||
| - `SPEC_FILE`: Path to the created spec file | ||
| - `FEATURE_NUM`: The numeric or timestamp prefix used |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| --- | ||
| description: "Initialize a Git repository with an initial commit" | ||
| --- | ||
|
|
||
| # Initialize Git Repository | ||
|
|
||
| Initialize a Git repository in the current project directory if one does not already exist. | ||
|
|
||
| ## Execution | ||
|
|
||
| Run the appropriate script from the project root: | ||
|
|
||
| - **Bash**: `.specify/extensions/git/scripts/bash/initialize-repo.sh` | ||
| - **PowerShell**: `.specify/extensions/git/scripts/powershell/initialize-repo.ps1` | ||
|
|
||
| If the extension scripts are not found, fall back to: | ||
| - **Bash**: `git init && git add . && git commit -m "Initial commit from Specify template"` | ||
| - **PowerShell**: `git init; git add .; git commit -m "Initial commit from Specify template"` | ||
|
|
||
| The script handles all checks internally: | ||
| - Skips if Git is not available | ||
| - Skips if already inside a Git repository | ||
| - Runs `git init`, `git add .`, and `git commit` with an initial commit message | ||
|
|
||
| ## Customization | ||
|
|
||
| Replace the script to add project-specific Git initialization steps: | ||
| - Custom `.gitignore` templates | ||
| - Default branch naming (`git config init.defaultBranch`) | ||
| - Git LFS setup | ||
| - Git hooks installation | ||
| - Commit signing configuration | ||
| - Git Flow initialization | ||
|
|
||
| ## Output | ||
|
|
||
| On success: | ||
| - `✓ Git repository initialized` | ||
|
|
||
| ## Graceful Degradation | ||
|
|
||
| If Git is not installed: | ||
| - Warn the user | ||
| - Skip repository initialization | ||
| - The project continues to function without Git (specs can still be created under `specs/`) | ||
|
|
||
| If Git is installed but `git init`, `git add .`, or `git commit` fails: | ||
| - Surface the error to the user | ||
| - Stop this command rather than continuing with a partially initialized repository |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.