<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>VS Code 開發環境 - Bobo 的學思山丘</title><description>用命令面板的 Git: Stage Changes + Git: Commit Staged，不離開檔案就能只 commit 當下這一份。但第一步沒 stage 到時，Commit Staged 一樣會問要不要把全部變更帶走。</description><link>https://bobochen.dev/</link><item><title>VS Code 只 commit 當下這個檔案：兩個指令就搞定</title><link>https://bobochen.dev/blog/vscode-commit-current-file-command-palette/</link><guid isPermaLink="true">https://bobochen.dev/blog/vscode-commit-current-file-command-palette/</guid><description>用命令面板的 Git: Stage Changes + Git: Commit Staged，不離開檔案就能只 commit 當下這一份。但第一步沒 stage 到時，Commit Staged 一樣會問要不要把全部變更帶走。</description><pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate><content:encoded>有時候改好一個檔案，想要馬上把開著的這一份檔案 commit 掉。

但又不想移開鍵盤，去 Source Control 面板裡用滑鼠找檔案、點按鈕。

## 只 commit 當下開啟的檔案

命令面板兩個指令就夠：

```text
⌘⇧P → Git: Stage Changes     # 只 stage 目前作用中的這個檔案
⌘⇧P → Git: Commit Staged     # 只 commit 已 stage 的內容
```

先講結果：**第一步沒 stage 到東西時，第二步會做什麼，取決於兩個設定。**

| `git.enableSmartCommit` | `git.suggestSmartCommit` | stage 區是空的，執行 Commit Staged |
|---|---|---|
| `false`（預設） | `true`（預設） | 跳對話框，問要不要把**全部變更**一起 commit |
| `false` | `false` | 什麼都不做，也不提示 |
| `true` | 任意 | 不問，直接把全部變更 commit |



## 坑一：Stage Changes 沒抓到檔案時，不會有任何提示

`Git: Stage Changes` 沒帶參數時，會去問「目前作用中的編輯器是哪個檔案」：

```ts
// extensions/git/src/commands.ts（VS Code 1.136.1）
private getSCMResource(uri?: Uri): Resource | undefined {
    uri = uri ?? window.activeNotebookEditor?.notebook.uri ?? window.activeTextEditor?.document.uri;
```

問不到，就直接 `return`。

我實測過：作用中的分頁是擴充套件開的面板、不是文字檔時，執行 Stage Changes，檔案沒有被 stage，畫面上也沒有任何訊息。

這類面板不是文字編輯器，`activeTextEditor` 拿不到檔案。照同一段程式碼推，Markdown 預覽、設定頁這類非文字分頁應該也一樣，這幾個我沒逐一試。

## 坑二：Commit Staged 跟 Commit 走的是同一條路

名字裡寫著 Staged，很容易以為它是「安全版的 Commit」：沒 stage 東西就不動作。

我原本也這樣以為。翻了原始碼才發現不是：

```ts
@command(&apos;git.commitStaged&apos;, { repository: true })
async commitStaged(repository: Repository): Promise&lt;void&gt; {
    await this.commitWithAnyInput(repository, { all: false });
}
```

`Commit` 和 `Commit Staged` 最後都進到同一個 `smartCommit()`。stage 區是空的時候，判斷條件裡看的是 `!opts.all`，而 `all: false` 剛好成立：

```ts
if (!noUnstagedChanges &amp;&amp; noStagedChanges &amp;&amp; !enableSmartCommit &amp;&amp; !opts.all &amp;&amp; !opts.amend) {
```

所以兩個指令跳出來的是同一個對話框：

```text
There are no staged changes to commit.

Would you like to stage all your changes and commit them directly?

Yes / Always / Never
```

## 按下 Yes，我的 repo 會多一個 74 個檔案的 commit

按下 `Yes` 或 `Always` 之後，`git.smartCommitChanges` 的預設值是 `all`，VS Code 會執行：

```bash
git add -A -- .
```

`-A` 會把 untracked 檔案一起加進去。拿我寫這篇時的 repo 用 `git add -A -n -- .`（dry-run，只列不加）來算：

| 狀態 | 數量 |
|---|---|
| 已追蹤、有修改 | 4 |
| untracked 檔案（`git status` 只顯示 41 項，因為整個資料夾算一項） | 70 |
| **按下 Yes 後會進 commit 的** | **74** |

我只想 commit 1 個檔案。

`Always` 更麻煩。它會把 `git.enableSmartCommit: true` 寫進 User Settings，之後遇到同樣情況就不問了，直接全部 commit。這段是讀原始碼得出的，我沒有真的按 Always 去試。

## 3 分鐘上手：兩個指令，加一條退路

**最小可用流程**：

```text
1. 點回要 commit 的檔案，確認作用中的是文字分頁
2. ⌘⇧P → Git: Stage Changes
3. ⌘⇧P → Git: Commit Staged
4. 開出 COMMIT_EDITMSG 分頁 → 寫 message → 按分頁裡的 Commit 按鈕
5. 如果第 3 步跳出 &quot;There are no staged changes&quot; → 按 Esc，回到第 1 步
```

幾個補充：

- Source Control 輸入框裡如果已經有字，第 4 步會直接拿那段當 message，不開分頁。
- 只想 commit 其中幾行：選取後按 `⌘K ⌘⌥S`（Git: Stage Selected Ranges，內建快捷鍵）。
- 以前按過 Always 的話：到 User Settings 找 `git.enableSmartCommit`，改回 `false`。

寧可沒反應、也不要誤 commit 的話，可以把對話框也關掉（對應上面表格第二列）：

```json
{
  &quot;git.enableSmartCommit&quot;: false,
  &quot;git.suggestSmartCommit&quot;: false
}
```

常用的話，再綁兩個快捷鍵（`Preferences: Open Keyboard Shortcuts (JSON)`）：

```json
[
  { &quot;key&quot;: &quot;cmd+alt+s&quot;, &quot;command&quot;: &quot;git.stage&quot;, &quot;when&quot;: &quot;editorTextFocus&quot; },
  { &quot;key&quot;: &quot;cmd+alt+c&quot;, &quot;command&quot;: &quot;git.commitStaged&quot; }
]
```

`when: editorTextFocus` 讓 stage 快捷鍵只在游標停在文字編輯器時生效，剛好避開坑一。

## 反思

### 技術面

`Commit Staged` 這個名字描述的是正常情況下它做什麼，沒有保證 stage 區是空的時候它不做什麼。邊界行為要看那個 `if`，不能看指令名稱。

「沒有提示」本身就是風險。Stage Changes 失敗時不出聲，真正出聲的是下一步的對話框，而它問的是要不要把全部變更帶走。

### 心態面

我把 Commit Staged 當成安全版的 Commit，理由只有一個：被指令名稱給誤導了。

如果沒有要寫成文章、去翻原始碼，這個誤解會一直留著，直到哪天某個 commit 裡多出 73 個不該進去的檔案。我對工具的信任，有一部分其實是建立在命名上。

### 有趣發現

Git 擴充內建的快捷鍵只有三個：Stage、Unstage、Revert，而且全都是「選取範圍」版本。最常用的整檔 stage 反而沒有預設快捷鍵，得自己綁。

`Always` 寫入的是 User Settings，不是這個 repo 的 Workspace Settings。在一個專案按一次，所有專案都跟著生效。

指令名稱是承諾的摘要，`if` 才是承諾本身。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.C7pLUS57.webp" medium="image"/><category>VS Code</category><category>Git</category><category>效率</category><category>開發技巧</category><enclosure url="https://bobochen.dev/_astro/cover.C7pLUS57.webp" length="0" type="image/png"/></item></channel></rss>