# 在 Fork 使用 Husky 進行 pre-commit 發生錯誤

## **Ref**

* Husky: [**https://typicode.github.io/husky/#/?id=command-not-found**](https://typicode.github.io/husky/#/?id=command-not-found)
    
* [dev-fork-issue-1227:](https://typicode.github.io/husky/#/?id=command-not-found) [**https://github.com/fork-dev/Tracker/issues/1227**](https://github.com/fork-dev/Tracker/issues/1227)
    
* [dev-fork-issue-1261:](https://typicode.github.io/husky/#/?id=command-not-found) [**https://github.com/fork-dev/Tracker/issues/1261**](https://github.com/fork-dev/Tracker/issues/1261)
    

## 情境

因為平常習慣用用 [Git-Fork](https://git-fork.com/) 來進行 git 相關作業, 但在試圖使用 husky 的 pre commit hook 時遇到一些問題.

```bash
.husky/pre-commit: line 4: npx: command not found
husky - pre-commit hook exited with code 127 (error)
```

按照錯誤訊息的描述, 是在執行 **.husky/pre-commit** 這個指令的時候, 讀取該腳本的的第 4 行發生 `npx command not found`.

## **先說解法**

老實說, 這是我第一次接觸 [**Husky**](https://typicode.github.io/husky) 就拿著關鍵字亂查了一下. 而問題發生的原因, 依據 [**Command-not-found**](https://typicode.github.io/husky/#/?id=command-not-found) 的描述, 有可能是 **npx** 沒辦法執行, 或是 node 環境發生問題. 推測大概是系統環境變數無法正常被 Fork 工具存取到. 另外建立了 **~/.huskyrc** 確實解決了我的問題.

```bash
# ~/.huskyrc
# This loads nvm.sh and sets the correct PATH before running hook
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
```

上面的腳本大概解釋如下

* 第一部分 `-s "$NVM_DIR/`[`nvm.sh`](http://nvm.sh)`"` 會檢查 `$NVM_DIR` 目錄下的 [*nvm.sh*](http://nvm.sh) 檔案是否存在.
    
* 第二部分 `&& \. "$NVM_DIR/`[`nvm.sh`](http://nvm.sh) 中的 **&&** 是一個邏輯運算符，它表示當第一部分條件成立時才會執行第二部分. `\.` 會執行 [nvm.sh](http://nvm.sh) 檔案中的程式碼.
    

## Why

事實上, 我確定我有上面的相關設定, 我是用 **NVM (Node Version Manager)** 管理我的 Node 版本沒錯. 依據 NVM 的官方文件, 我在 `~/.bash_profile` 裡面有了這段設定.

```bash
# nvm
export NVM_DIR="$HOME/.nvm"
. "/usr/local/opt/nvm/nvm.sh"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads
```

我另外分別於 `~/.bash_profile` 與 `~/.zshrc` 加入 `echo` 確認過載入順序是

1. ~/.zshrc
    
2. ~/.bash\_profile
    

### [**fork-dev Issue 1227**](https://github.com/fork-dev/Tracker/issues/1227)

在這個討論串內, 確實有提到 Fork 運行時, 是一個獨立的 shell 環境, 不會特別去載入使用者的 PATH 環境變數. 意思是不會讀取到 `~/.zshrc` 這些 PATH, 導致沒有載入到 **NVM** 的相關環境變數.

### [**fork-dev Issue 1261**](https://github.com/fork-dev/Tracker/issues/1261)

然而在這個討論串內, 提到用指令打開 Fork `open -a Fork`, 會讓 Fork 繼承 Parent process, 也就是會繼承 runtime 指令的環境變數. 在這個階段下打開 Fork 又可以 commit 了. 但我自己的習慣都是用 Mac Spotlight 來開啟相關工具, 所以這個解法對我來說有點不順手 XD.

反正 Fork 執行 git commit 的時候會觸發 husky (我並不是很確定 husky 運作方式 XD) 所以我在 **~/.husky/pre-commit** 檔案內加入 `echo $PATH`, 間接的確認到 Fork 的 runtime 的環境變數了.

```bash
/usr/local/Cellar/git/2.32.0/libexec/git-core
/Applications/Fork.app/Contents/Resources/git-instance/git-lfs
/Applications/Fork.app/Contents/Resources/gitflow-avh
/opt/homebrew/bin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
```

裡面當然沒有 NVM 相關環境變數 XD, 也沒有 `~/.zshrc` 與 `~/.bash_profile`.

## **總結**

### 解法 1

採用 **~/.huskyrc** 作法, 讓 husky 指令能夠讀取到 nvm 環境變數.

```bash
# ~/.huskyrc
# This loads nvm.sh and sets the correct PATH before running hook
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
```

但目前 huskyrc 似乎已經廢棄了, 但可以依據 [官方](https://typicode.github.io/husky/zh/how-to.html#%E5%90%AF%E5%8A%A8%E6%96%87%E4%BB%B6) 說明, 檔名路徑修改為 `~/.config/husky/init.sh`.

### **解法 2**

用 terminal 打開 Fork,

```bash
open -a Fork
```

### **解法 3**

把當下的 node 相關指令, 用建立捷徑的方式 (symbolic link), 把 node 相關的 bin 連結到 `/usr/local/bin`, 但這樣設定下去 node 就變成全域 (有好有壞).

```bash

ln -s $(which node) /usr/local/bin/node
```
