> ## Documentation Index
> Fetch the complete documentation index at: https://docs.diversion.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# プリコミットフック

> コミット前にカスタムスクリプトを実行して、変更の検証、標準の適用、チェックの自動化を行います。

プリコミットフックを使うと、各コミットの前に変更を自動的に検証するカスタムスクリプトを実行できます。スクリプトが非ゼロのコードで終了するとコミットはブロックされ、問題がリポジトリに到達する前に修正するチャンスが得られます。

## 概要

フックはリポジトリのルートにある `.dvhooks/` ディレクトリに格納される実行可能スクリプトです。リポジトリ内に存在するため、他のファイルと同様にすべてのコラボレーターと同期されます。

**一般的なユースケース:**

* Lint と構文チェック
* コードフォーマットの強制
* 大きなファイルや禁止ファイルのコミット防止
* プロジェクト固有のカスタム検証

**仕組み:**

* コミット前に、Diversion は `.dvhooks/pre-commit` スクリプトを、コミットされるファイルをコマンドライン引数として渡して実行します
* 終了コード `0` はフック合格を意味し、コミットは続行されます
* 非ゼロの終了コードはフック失敗を意味し、コミットはブロックされます
* フックの stdout/stderr 出力はユーザーに表示されます

<Note>
  プリコミットフックはクライアント側のみです。CLI またはデスクトップアプリでコミットするときに実行されます。WebApp または API を通じて直接行われるコミットはフックをバイパスします。
</Note>

## プリコミットフックの作成

<Steps>
  <Step title="hooks ディレクトリを作成">
    リポジトリのルートに `.dvhooks` ディレクトリを作成します:

    ```bash theme={null}
    mkdir .dvhooks
    ```
  </Step>

  <Step title="フックスクリプトを作成">
    `.dvhooks/` 内に `pre-commit` スクリプトを作成します。スクリプトは実行可能であればどんな言語でも書けます。

    <CodeGroup>
      ```bash Mac/Linux (.dvhooks/pre-commit) theme={null}
      #!/bin/sh
      echo "Running pre-commit checks..."

      # Committed files are passed as arguments ($@)
      for file in "$@"; do
        if echo "$file" | grep -q '\.js$'; then
          if grep -q "console.log" "$file"; then
            echo "Error: Remove console.log from $file before committing."
            exit 1
          fi
        fi
      done

      echo "All checks passed."
      exit 0
      ```

      ```bat Windows (.dvhooks/pre-commit.bat) theme={null}
      @echo off
      echo Running pre-commit checks...

      REM Committed files are passed as arguments (%*)
      for %%f in (%*) do (
        echo Checking %%f
      )

      echo All checks passed.
      exit /b 0
      ```

      ```powershell Windows (.dvhooks/pre-commit.ps1) theme={null}
      Write-Host "Running pre-commit checks..."

      # Committed files are passed as arguments ($args)
      foreach ($file in $args) {
        if ($file -match '\.js$') {
          if (Select-String -Path $file -Pattern "console.log" -Quiet) {
            Write-Host "Error: Remove console.log from $file before committing."
            exit 1
          }
        }
      }

      Write-Host "All checks passed."
      exit 0
      ```
    </CodeGroup>

    Mac/Linux では、スクリプトを実行可能にします:

    ```bash theme={null}
    chmod +x .dvhooks/pre-commit
    ```
  </Step>

  <Step title="フックをコミット">
    `.dvhooks/` ディレクトリをコミットして、コラボレーターとフックを共有します:

    ```bash theme={null}
    dv commit .dvhooks -m "Add pre-commit hook"
    ```

    コミットされると、そのブランチのすべてのコラボレーターがフックを持つようになり、コミット前に自動的に実行されます。
  </Step>
</Steps>

## ファイル引数

コミットされるファイルは、フックスクリプトに **コマンドライン引数** として渡されます。スクリプトは `$@` (Mac/Linux) または `%*` (Windows) 経由でアクセスできます。

ファイルリストが 1 回のコマンド呼び出しには大きすぎる場合、Diversion は自動的にチャンクに分割し、フックを並列に複数回実行します。いずれかの呼び出しが失敗した場合、コミットはブロックされます。

**例 — コミット対象のファイルから大きなバイナリをチェック:**

<CodeGroup>
  ```bash Mac/Linux theme={null}
  #!/bin/sh
  # Reject files larger than 100MB
  MAX_SIZE=$((100 * 1024 * 1024))
  for file in "$@"; do
    if [ -f "$file" ]; then
      size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
      if [ "$size" -gt "$MAX_SIZE" ]; then
        echo "Error: $file is too large ($(($size / 1024 / 1024))MB, limit 100MB)."
        exit 1
      fi
    fi
  done

  exit 0
  ```

  ```bat Windows theme={null}
  @echo off
  REM Check committed files
  for %%f in (%*) do (
    echo Checking: %%f
  )
  exit /b 0
  ```
</CodeGroup>

## 環境変数

Diversion は、環境変数経由でもコンテキストをフックスクリプトに渡します:

| 変数                  | 説明              |
| ------------------- | --------------- |
| `DV_REPO_ROOT`      | ワークスペースルートの絶対パス |
| `DV_COMMIT_MESSAGE` | コミットメッセージ       |
| `DV_BRANCH`         | 現在のブランチ名        |

**例 — コミットメッセージにチケット番号を必須にする:**

<CodeGroup>
  ```bash Mac/Linux theme={null}
  #!/bin/sh
  # Require commit messages to contain a ticket reference (e.g., PROJ-123)
  if ! echo "$DV_COMMIT_MESSAGE" | grep -qE '[A-Z]+-[0-9]+'; then
    echo "Error: Commit message must include a ticket number (e.g., PROJ-123)."
    echo "Your message: $DV_COMMIT_MESSAGE"
    exit 1
  fi

  exit 0
  ```

  ```bat Windows theme={null}
  @echo off
  REM Require commit messages to contain a ticket reference (e.g., PROJ-123)
  echo %DV_COMMIT_MESSAGE% | findstr /R "[A-Z]*-[0-9]*" >nul 2>&1
  if %errorlevel% neq 0 (
    echo Error: Commit message must include a ticket number (e.g., PROJ-123).
    echo Your message: %DV_COMMIT_MESSAGE%
    exit /b 1
  )

  exit /b 0
  ```
</CodeGroup>

## フックをスキップする

`--no-verify` フラグを使用すると、1 回のコミットだけプリコミットフックをバイパスできます:

```bash theme={null}
dv commit -a -m "quick fix" --no-verify
```

これは、検証を実行せずにコミットしなければならない緊急の修正に便利です。

## 挙動の詳細

* **タイムアウト**: フックには 60 秒のタイムアウトがあります。時間内に完了しない場合、タイムアウトメッセージとともにコミットがブロックされます。
* **作業ディレクトリ**: フックはワークスペースルートを作業ディレクトリとして実行されます。
* **出力の上限**: フックの出力は 1 MB に制限されます。それを超える出力は切り捨てられます。
* **出力の表示**: フックの出力は、成功しても失敗しても常にユーザーに表示されます。
* **プラットフォーム検出**:
  * **Mac/Linux**: Diversion は `.dvhooks/` 内の `pre-commit` という名前の実行可能ファイルを探します。ファイルが存在しても実行可能でない場合、`chmod +x` の実行を促すエラーが表示されます。
  * **Windows**: Diversion は `.dvhooks/` 内の `pre-commit.bat`、`pre-commit.cmd`、`pre-commit.ps1` を (この順序で) 探します。
