Переглянути джерело

Feat: Enhance AI-powered Git assistant with rebase tools

This commit significantly expands the functionality of the AI-powered
Git assistant by adding features for suggesting and automating
interactive rebase operations.  It introduces:

-   AI-powered `fixup` suggestion (finds commits that look like small
    fixes to their predecessors).
-   AI-powered `reword` suggestion (finds commits with messages that
    could be improved).
-   Automatic rebase capabilities (with safety backups) for applying
    fixups and rewording commits.
-   A new `ai-commit.sh` script that dispatches to the appropriate
    Python script based on flags.
-   Two new Python scripts: `git_rebase_ai.py` and `git_reword_ai.py`.
-   Expanded documentation, including Makefile usage instructions,
    details on rebase workflows, and descriptions of all files.

The previous version only supported commit message generation. Now,
developers can leverage AI to streamline interactive rebases, improving
commit history quality and consistency.
seno 3 днів тому
батько
коміт
e2b59427f0
2 змінених файлів з 174 додано та 47 видалено
  1. 173 46
      README.md
  2. 1 1
      ai-commit.sh

+ 173 - 46
README.md

@@ -1,77 +1,204 @@
-# AI-Powered Git Commit Message Generator
+# AI-Powered Git Assistant
 
-This tool automatically generates Git commit messages based on your staged changes using the Google Gemini API. It analyzes the diff of your staged files and suggests a commit message following conventional commit standards.
+This tool leverages the Google Gemini API to assist with common Git tasks, including generating commit messages, suggesting `fixup` operations for interactive rebases, and suggesting `reword` operations with improved commit messages.
 
 ## Features
 
-- Analyzes staged Git diffs.
-- Generates commit messages (subject and body) using the Gemini API.
-- Follows standard Git commit message conventions (imperative mood, character limits, separation of subject/body).
-- Runs in a Docker container for a consistent environment.
-- Prompts for user confirmation before creating the commit.
+- **AI Commit Message Generation:** Analyzes staged Git diffs and generates conventional commit messages (subject and body). Supports amending previous commits.
+- **AI Rebase Fixup Suggestions:** Analyzes a range of commits (compared to an upstream branch) and suggests `fixup` operations for commits that appear to be minor corrections to their predecessors. Can optionally attempt to perform the rebase automatically.
+- **AI Rebase Reword Suggestions:** Analyzes a range of commits and suggests improved commit messages (`reword` operations) for those that don't follow conventions or lack clarity. Can optionally attempt to perform the rebase automatically.
+- **Interactive Confirmation:** Prompts for user confirmation before executing Git commands like `commit` or `rebase`.
+- **Contextual Awareness (Commit):** Can request content of specific project files (with user permission) to generate more accurate commit messages.
+- **Contextual Awareness (Rebase):** Can request content of specific files *at specific commits* (with user permission) to improve fixup suggestions.
+- **Safety:** Creates backup branches before attempting automatic rebases.
+- **Dockerized:** Runs in a Docker container for a consistent environment.
+- **Makefile:** Provides convenient shortcuts for common tasks.
 
 ## Prerequisites
 
 - **Git:** Must be installed on your host machine.
 - **Docker:** Must be installed and running on your host machine.
-- **Gemini API Key:** You need an API key from Google Cloud.
+- **Gemini API Key:** You need an API key from Google AI Studio or Google Cloud.
+- **Make (Optional):** For using the Makefile shortcuts.
 
 ## Setup
 
 1.  **Build the Docker Image:**
-
+    You can use the provided Makefile:
+    ```bash
+    make build
+    ```
+    Or build manually:
     ```bash
     docker build -t docker.senomas.com/commit:1.0 .
     ```
+    _(Note: The tag `docker.senomas.com/commit:1.0` is used by default. You can override it using the `DOCKER_IMAGE_NAME` environment variable if needed, e.g., `export DOCKER_IMAGE_NAME=my-custom-image:latest`.)_
 
-    _(Note: The tag `docker.senomas.com/commit:1.0` is used in the `ai-commit.sh` script. You can change it if needed, but make sure to update the script accordingly.)_
-
-2.  **Set Environment Variable:**
-    Export your Gemini API key as an environment variable:
+2.  **Set Environment Variables:**
+    Export your Gemini API key:
     ```bash
     export GEMINI_API_KEY='YOUR_API_KEY'
     ```
-    _(Replace `YOUR_API_KEY` with your actual key. You might want to add this line to your shell profile (e.g., `.bashrc`, `.zshrc`, `config.fish`) for persistence.)_
+    Optionally, set the Gemini model to use (defaults to `gemini-1.5-flash-latest` if not set):
+    ```bash
+    export GEMINI_MODEL='gemini-1.5-pro-latest' # Or another compatible model
+    ```
+    _(Replace `YOUR_API_KEY` with your actual key. Add these lines to your shell profile (e.g., `.bashrc`, `.zshrc`, `config.fish`) for persistence.)_
 
 ## Usage
 
-1.  **Stage your changes:** Use `git add` to stage the files you want to include in the commit.
-2.  **Run the script:**
-    *   **For a new commit:** Execute the `ai-commit.sh` script from the root of your Git repository:
-        ```bash
-        ./ai-commit.sh
-        ```
-    *   **To amend the previous commit:** Use the `-a` or `--amend` flag:
-        ```bash
-        ./ai-commit.sh -a
-        # or
-        ./ai-commit.sh --amend
-        ```
-3.  **Review and Confirm:** The script will:
-    - Fetch the staged diff (for a new commit) or the diff representing the changes to be amended (for an amend).
-    - Generate a commit message using the Gemini API.
-    - Print the generated message.
-    - Ask for your confirmation (`y/n`).
-4.  **Commit:** If you confirm ('y'), the script will create the commit using the generated message. If you decline ('n'), the commit will be aborted.
+You can use the `Makefile` for convenience or run the `ai-commit.sh` script directly.
+
+### Using Makefile
+
+-   **Generate Commit Message:** Stage changes (`git add ...`), then run:
+    ```bash
+    make commit
+    ```
+    To amend the previous commit:
+    ```bash
+    make commit ARGS="-a"
+    ```
+-   **Suggest Rebase Fixups:** Compares current branch to `upstream/main` by default.
+    ```bash
+    make rebase
+    ```
+    To compare against a different upstream reference and only show instructions (no auto-rebase):
+    ```bash
+    make rebase UPSTREAM_REF="origin/develop" ARGS="--instruct"
+    ```
+-   **Suggest Rebase Rewords:** Compares current branch to `upstream/main` by default.
+    ```bash
+    make reword
+    ```
+    To compare against a different upstream reference and only show instructions (no auto-rebase):
+    ```bash
+    make reword UPSTREAM_REF="origin/develop" ARGS="--instruct"
+    ```
+
+### Using `ai-commit.sh` Directly
+
+The `ai-commit.sh` script acts as the main entry point, selecting the appropriate Python script based on flags.
+
+-   **Generate Commit Message (Default):**
+    Stage changes (`git add ...`), then run:
+    ```bash
+    ./ai-commit.sh
+    ```
+    To amend the previous commit:
+    ```bash
+    ./ai-commit.sh -a
+    # or
+    ./ai-commit.sh --amend
+    ```
+-   **Suggest Rebase Fixups (`-r` flag):**
+    ```bash
+    # Compare against upstream/main (default) and attempt auto-rebase
+    ./ai-commit.sh -r
+
+    # Compare against origin/develop and attempt auto-rebase
+    ./ai-commit.sh -r origin/develop
+
+    # Compare against upstream/main, show instructions only (no auto-rebase)
+    ./ai-commit.sh -r --instruct
+
+    # Compare against origin/develop, show instructions only
+    ./ai-commit.sh -r origin/develop --instruct
+    ```
+-   **Suggest Rebase Rewords (`-w` flag):**
+    ```bash
+    # Compare against upstream/main (default) and attempt auto-reword
+    ./ai-commit.sh -w
+
+    # Compare against origin/develop and attempt auto-reword
+    ./ai-commit.sh -w origin/develop
+
+    # Compare against upstream/main, show instructions only (no auto-reword)
+    ./ai-commit.sh -w --instruct
+
+    # Compare against origin/develop, show instructions only
+    ./ai-commit.sh -w origin/develop --instruct
+    ```
+
+### Workflow Details
+
+1.  **Commit:**
+    - Stage your changes (`git add ...`).
+    - Run `make commit` or `./ai-commit.sh` (optionally with `-a`).
+    - The tool analyzes the staged diff.
+    - It may ask for permission to read specific project files for better context.
+    - It generates a commit message.
+    - It prints the message and asks for confirmation (`y/n`).
+    - If confirmed, it runs `git commit` (or `git commit --amend`).
+
+2.  **Rebase Fixup:**
+    - Ensure your branch is up-to-date with the remote if necessary.
+    - Run `make rebase [UPSTREAM_REF=...] [ARGS=...]` or `./ai-commit.sh -r [upstream_ref] [--instruct]`.
+    - The tool analyzes commits between the `upstream_ref` (e.g., `upstream/main`) and your current branch (`HEAD`).
+    - It identifies commits that look like small fixes to their immediate predecessor.
+    - It may ask for permission to read specific files *at specific commits* for better context.
+    - It prints the suggested `fixup` operations.
+    - **If `--instruct` is NOT used:**
+        - It creates a backup branch (e.g., `your-branch-backup-TIMESTAMP`).
+        - It asks for confirmation to attempt the automatic rebase.
+        - If confirmed, it runs `git rebase -i` non-interactively using a generated script to apply the fixups.
+        - If the automatic rebase fails (e.g., conflicts), it attempts to abort and provides instructions for manual rebase.
+    - **If `--instruct` IS used:**
+        - It prints instructions on how to perform the rebase manually using the suggestions.
+
+3.  **Rebase Reword:**
+    - Ensure your branch is up-to-date.
+    - Run `make reword [UPSTREAM_REF=...] [ARGS=...]` or `./ai-commit.sh -w [upstream_ref] [--instruct]`.
+    - The tool analyzes commits between the `upstream_ref` and `HEAD`.
+    - It identifies commits with messages that could be improved (clarity, convention adherence).
+    - It generates a complete new commit message (subject and body) for each suggested reword.
+    - It prints the suggested `reword` operations with the new messages.
+    - **If `--instruct` is NOT used:**
+        - It creates a backup branch.
+        - It asks for confirmation to attempt the automatic rebase.
+        - If confirmed, it runs `git rebase -i` non-interactively using generated scripts to mark commits for reword and supply the new messages.
+        - If the automatic rebase fails, it attempts to abort and provides instructions for manual rebase.
+    - **If `--instruct` IS used:**
+        - It prints instructions on how to perform the rebase manually, including the suggested new messages to copy.
 
 ## How it Works
 
-1.  The `ai-commit.sh` script runs the `git_commit_ai.py` script inside a Docker container (`docker.senomas.com/commit:1.0`).
-2.  It mounts the current directory (`pwd`) as `/repo` inside the container, allowing the script to access your Git repository.
-3.  It mounts your `.gitconfig` and `.git-credentials` (read-only) for Git operations within the container.
-4.  It passes the `GEMINI_API_KEY` environment variable into the container.
-5.  It forwards any arguments passed to `ai-commit.sh` (like `-a` or `--amend`) to the Python script inside the container.
-6.  The `git_commit_ai.py` script:
-    - Parses command-line arguments (e.g., `--amend`).
-    - Retrieves the staged diff using `git diff --staged`.
-    - Sends the diff to the Gemini API with a prompt asking for a commit message.
-    - Receives the generated message.
-    - Prompts the user for confirmation (mentioning if it's an amend).
-    - If confirmed, runs `git commit -m "..."` or `git commit --amend -m "..."` with the generated message.
+1.  The `Makefile` provides simple targets that call `ai-commit.sh` with appropriate flags and arguments.
+2.  The `ai-commit.sh` script determines which Python script to run based on the presence of `-r` (rebase fixup) or `-w` (rebase reword) flags. If neither is present, it defaults to commit message generation.
+3.  It runs the selected Python script (`git_commit_ai.py`, `git_rebase_ai.py`, or `git_reword_ai.py`) inside the specified Docker container (`docker.senomas.com/commit:1.0` by default).
+4.  It mounts the current directory (`pwd`) as `/repo`, `.gitconfig`, and `.git-credentials` (read-only) into the container.
+5.  It passes the `GEMINI_API_KEY` and `GEMINI_MODEL` environment variables into the container.
+6.  It forwards relevant arguments (like `-a`, `--amend`, `upstream_ref`, `--instruct`) to the Python script.
+7.  **`git_commit_ai.py`:**
+    - Parses arguments (`--amend`).
+    - Gets staged diff (`git diff --staged` or `git diff HEAD~1 --staged`).
+    - Gets project file list (`git ls-tree`).
+    - Interacts with Gemini API, potentially requesting file content (`Request content for file: ...`), to generate a commit message.
+    - Prompts user for confirmation.
+    - Runs `git commit`.
+8.  **`git_rebase_ai.py`:**
+    - Parses arguments (`upstream_ref`, `--instruct`).
+    - Finds merge base (`git merge-base`).
+    - Gets commits, file structure, and diff for the range.
+    - Interacts with Gemini API, potentially requesting file content at specific commits (`REQUEST_FILES: [...]`), to suggest `FIXUP: ... INTO ...` lines.
+    - Parses suggestions.
+    - If not `--instruct`, creates backup, confirms, and attempts automatic rebase using `GIT_SEQUENCE_EDITOR` script to change `pick` to `f`. Handles potential failures and aborts.
+    - If `--instruct`, prints manual instructions.
+9.  **`git_reword_ai.py`:**
+    - Parses arguments (`upstream_ref`, `--instruct`).
+    - Finds merge base.
+    - Gets commits and diff for the range.
+    - Interacts with Gemini API to suggest `REWORD: ... NEW_MESSAGE: ... END_MESSAGE` blocks.
+    - Parses suggestions.
+    - If not `--instruct`, creates backup, confirms, and attempts automatic rebase using `GIT_SEQUENCE_EDITOR` (changes `pick` to `r`) and `GIT_EDITOR` (supplies new message via env var) scripts. Handles potential failures and aborts.
+    - If `--instruct`, prints manual instructions with new messages.
 
 ## Files
 
-- `git_commit_ai.py`: The main Python script that interacts with Git and the Gemini API.
+- `ai-commit.sh`: Main entry script, selects Python script based on flags.
+- `git_commit_ai.py`: Handles AI commit message generation.
+- `git_rebase_ai.py`: Handles AI rebase fixup suggestions and automation.
+- `git_reword_ai.py`: Handles AI rebase reword suggestions and automation.
 - `Dockerfile`: Defines the Docker image environment.
-- `ai-commit.sh`: A helper script to easily run the tool in Docker.
+- `Makefile`: Provides convenience targets (`build`, `commit`, `rebase`, `reword`).
 - `README.md`: This file.

+ 1 - 1
ai-commit.sh

@@ -31,4 +31,4 @@ docker run --rm -it \
 	-e GEMINI_API_KEY="$GEMINI_API_KEY" \
 	-e GEMINI_MODEL="${GEMINI_MODEL:-gemini-2.0-flash}" \
 	-u "$(id -u):$(id -g)" \
-	${DOCKER_IMAGE_NAME:-docker.senomas.com/commit:1.0} "$script_to_run" ${docker_args[@]}
+	${DOCKER_IMAGE_NAME:-docker.senomas.com/commit:1.1} "$script_to_run" ${docker_args[@]}