﻿# 如何設定 Husky.Net 讓開發團隊確保一致的程式碼風格

在 .NET 專案設定 [Husky](https://typicode.github.io/husky/) 實在有夠簡單，只要用 [Husky.Net](https://alirezanet.github.io/Husky.Net/) 工具即可，一分鐘就可以搞定所有設定。不過我覺得 Husky.Net 官方文件的 [Getting Started](https://alirezanet.github.io/Husky.Net/guide/getting-started.html) 少了一些實務上的設定步驟，這會導致初學者不太容易一次就上手，所以我打算寫點文章來跟大家分享。

![Husky.Net Banner](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6ba2e15173a9248a812d-6b7924ee-9f92-45c3-88de-6fde90e741a5.webp)

### 首次安裝

如果你之前都沒有裝過這套工具，可以參考以下步驟快速設定：

```bash
# 先進入到你的專案資料夾
cd <Your project root directory>

# 初始化你的 .NET Local Tools
dotnet new tool-manifest

# 將 Husky 工具安裝到你的工具清單中
dotnet tool install Husky

# 初始化 Git Hooks 設定
dotnet husky install
```

初始化 Git hooks 設定之後，就可以加入你的第一個 pre-commit hook 設定。假設我希望每次在 `git commit` 之前都要執行 `dotnet format` 自動格式化程式碼，確保程式碼風格都能維持在最佳狀態。這裡我寫兩個版本給大家選擇：

1.  在 `git commit` 之前，驗證程式碼風格符合 `.editorconfig` 規範
    
    這段設定會將命令寫入 `.husky/pre-commit` 檔案中，如果該命令執行後的 exit code 不為 `0` 就會拒絕你的 `git commit` 命令！
    
    ```bash
    dotnet husky add pre-commit -c "dotnet format --verify-no-changes"
    ```
    
    > 注意: `dotnet format --verify-no-changes` 會針對整個專案進行程式碼風格檢查，如果專案的程式碼數量很多的話，每次 `git commit` 的速度就會非常慢，會影響版控的體驗。
    
2.  在 `git commit` 之前，自動格式化程式碼風格 (符合 `.editorconfig` 規範)
    
    這段設定會將命令寫入 `.husky/pre-commit` 檔案中，該命令執行後會自動修復所有程式碼，並且會在修改過後，將所有變更都加入 staged 清單，讓這些檔案都會自動被 commit 到 Git 之中！
    
    ```bash
    dotnet husky add pre-commit -c "dotnet format && git add -u"
    ```
    
    > 注意: `git add -u` 會將所有已修改的 tracked files 都再次加入到 staged 清單中。這個命令雖然看起來簡單，但是不太理想，因為我們並非每次版控都想要把所有變更加入版控，這點必須特別注意。
    

有鑑於上述兩個命令都不是非常理想，我真正理想中的執行邏輯，是我在維護專案的過程中，只有這次要 commit 的檔案才進行程式碼風格檢查或自動修正格式，這樣可以大幅提高版控的效率。

1.  建立 `.husky\pre-commit` 檔案
    
    ```bash
    dotnet husky add pre-commit
    ```
    
2.  編輯 `.husky\pre-commit` 檔案，將整個檔案內容清空，換成以下腳本內容：
    
    ```bash
    #!/bin/sh
    LC_ALL=C
    
    # Select files to format
    FILES=$(git diff --cached --name-only --diff-filter=ACM "*.cs" | sed 's| |\\ |g')
    [ -z "$FILES" ] && exit 0
    
    # Format all selected files
    echo "$FILES" | cat | xargs | sed -e 's/ /,/g' | xargs dotnet format --include
    
    # Add back the modified files to staging
    echo "$FILES" | xargs git add
    
    exit 0
    ```
    
    這段 Shell 腳本可以幫助你僅處理那些 `*.cs` 原始碼的變更清單，也就是你有先 `git add` 過的那些檔案，只有這些檔案會被 `dotnet format` 工具自動修正程式碼風格。
    

由於是首次設定，你只要將 `.config` 與 `.husky` 資料夾加入版控，就可以與開發團隊的其他人共享了！👍

### 團隊成員安裝

任何人將原始碼 `git clone` 回來後，只要輸入以下命令，就可以全自動初始化 Husky.Net 完成：

```bash
dotnet tool restore && dotnet husky install
```

這命令只需要在 `git clone` 之後做一次即可，只要沒這樣執行，你的 pre-commit hook 就不會自動執行。

當然，如果你已經初始化好了，但想暫時停用 Husky 的話，可以執行以下命令：

```bash
dotnet husky uninstall
```

### 介紹 Husky.Net 的 Task Runner

[Husky.Net](https://alirezanet.github.io/Husky.Net/) 有個 [Task Runner](https://alirezanet.github.io/Husky.Net/guide/task-runner.html) 功能，可以將要讓 `pre-commit` 執行的命令，改用另一種更抽象、更簡潔的方式執行。

以下是設定的步驟：

1.  初始化 `.husky/pre-commit` 檔案
    
    以下這段命令會將 `dotnet husky run` 命令寫入 `.husky/pre-commit` 檔案中：
    
    ```bash
    dotnet husky add pre-commit -c "dotnet husky run"
    ```
    
2.  編輯 `.husky/task-runner.json` 設定檔
    
    這段用到了幾個 `Husky.Net` 的 `Task Runner` 專屬的功能，一個是 `"${staged}"` 變數，他會自動代入所有 staged 的檔案。另一個則是 `include` 屬性，他可以指定只有 `**/*.cs` 與 `**/*.vb` 才會傳入 `${staged}` 變數。再來就是他有特別針對 Windows 作業系統進行優化，任何在 Windows 上面執行的命令與參數，可以在 `windows` 屬性進行覆寫，相當方便。
    
    以下範例看起來比上面的 shell script 好看多了：
    
    ```json
    {
       "$schema": "https://alirezanet.github.io/Husky.Net/schema.json",
       "tasks": [
          {
             "name": "dotnet-format",
             "command": "bash",
             "args": [ "-c", "dotnet", "format", "--include", "${staged}" ],
             "include": ["**/*.cs", "**/*.vb"],
             "windows": {
                "command": "cmd",
                "args": ["/c", "dotnet", "format", "--include", "${staged}" ]
             }
          }
       ]
    }
    ```
    

我認為學會這幾招已經很夠用了，更多應用技巧可以查看 [Husky.Net](https://alirezanet.github.io/Husky.Net/) 官方文件！👍

### 相關連結

-   [Husky.Net](https://alirezanet.github.io/Husky.Net/)
    -   [Getting Started](https://alirezanet.github.io/Husky.Net/guide/getting-started.html)
    -   [Task Runner](https://alirezanet.github.io/Husky.Net/guide/task-runner.html)
    -   [CSharp Scripts](https://alirezanet.github.io/Husky.Net/guide/csharp-script.html#examples)
-   [alirezanet/Husky.Net](https://github.com/alirezanet/husky.net) (GitHub)
    -   Git hooks made easy with Husky.Net internal task runner! 🐶 It brings the dev-dependency concept to the .NET world!
-   [開發 .NET 應用程式可利用 dotnet format 建立一致的程式碼風格](/post/2025/09/10/Use-dotnet-format-to-create-consistent-code-style)
