Git 完整教學:從指令列到 VS Code 圖形介面

Git 用來記錄檔案的版本、比較修改、建立分支、合併成果,也能和 GitHub、GitLab、Bitbucket 或自架伺服器協作。本篇從第一次安裝開始,逐步說明日常開發、VS Code 操作、遠端同步、衝突處理、版本回復與進階工具。

本文以 Windows 與 VS Code 為主要示範環境。Git 指令在 macOS、Linux 上大致相同;畫面名稱可能因 VS Code 版本與語言設定略有差異。

本文最後更新於 2026 年 8 月 28 日。若只想完成第一次提交,可先讀「第一次完整操作」;遇到問題時,再從目錄跳到對應章節。

目錄

展開目錄

先看懂 Git 在記錄什麼

Git 不只是把檔案複製成多份備份。每次提交(commit)都會記錄當時的專案快照、作者、時間、說明文字,以及上一個提交的位置。多數 Git 操作都在本機完成,沒有網路也能提交、切換分支與查看歷史。

一份 Git 專案通常會遇到以下區域:

區域 英文名稱 用途
工作目錄 Working tree 實際正在編輯的檔案
暫存區 Staging area/Index 挑選「下一次提交要包含哪些修改」
本機儲存庫 Local repository 儲存在 .git 裡的提交與分支歷史
遠端儲存庫 Remote repository GitHub、GitLab 或伺服器上的協作副本
flowchart LR A[工作目錄<br/>修改檔案] -->|git add| B[暫存區<br/>準備提交] B -->|git commit| C[本機儲存庫<br/>形成提交] C -->|git push| D[遠端儲存庫] D -->|git fetch| C D -->|git pull| A B -->|git restore --staged| A A -->|git restore| E[還原成已知版本]

git add 的作用是挑選下一次提交的內容,不等於上傳。git commit 只寫入本機歷史,git push 才會把本機提交送到遠端。

常見名詞

名詞 說明
Repository/repo Git 儲存庫,包含專案檔案與 .git 歷史資料
Commit 一次有說明文字的版本快照
Branch 指向某個提交的可移動名稱,例如 mainfeature/login
HEAD 目前所在的提交,通常會跟著目前分支移動
Remote 指向另一份儲存庫的名稱,最常見的是 origin
Clone 複製遠端儲存庫及其歷史到本機
Fetch 下載遠端新歷史,但不改目前工作檔案
Pull 先抓取,再把遠端變更整合到目前分支
Push 把本機提交送往遠端
Merge 合併兩條分支的歷史
Rebase 把一串提交改接到另一個基底上
Tag 固定指向特定提交的標記,常用於版本號

安裝 Git 與 VS Code

Windows

  1. Git 官方網站 安裝 Git for Windows。
  2. VS Code 官方網站 安裝 Visual Studio Code。
  3. 安裝 Git 時若不確定選項,可保留預設值。預設編輯器之後仍能改成 VS Code。
  4. 安裝完成後重開 VS Code,讓它重新偵測 Git。

在 PowerShell 或 VS Code 終端機檢查:

git --version
code --version

VS Code 的 Git 功能使用電腦上安裝的 Git,不是另外一套獨立版本控制系統。若左側沒有「原始檔控制」圖示,先確認 git --version 能正常輸出版本。

macOS

可以安裝 Xcode Command Line Tools,或使用 Homebrew:

xcode-select --install
brew install git

Ubuntu/Debian

sudo apt update
sudo apt install git

第一次設定 Git

設定提交者姓名與電子郵件

git config --global user.name "你的名字"
git config --global user.email "[email protected]"

這些資料會寫進之後建立的提交。若 GitHub 帳號啟用了隱私信箱,可使用 GitHub 提供的 noreply 地址。

檢查目前設定與來源:

git config --list --show-origin

設定只套用目前儲存庫時,不加 --global

git config user.name "專案使用的名字"
git config user.email "[email protected]"

Git 設定有三個常見層級:

層級 指令 影響範圍
System git config --system 整台電腦的所有使用者
Global git config --global 目前作業系統使用者的所有儲存庫
Local git config --local 目前儲存庫,優先權最高

建議的基本設定

git config --global init.defaultBranch main
git config --global core.editor "code --wait"

第一行讓新儲存庫的預設分支叫 main。第二行讓需要輸入長訊息時,Git 以 VS Code 開啟編輯器,並等待視窗關閉後繼續。

Windows 常見換行設定:

git config --global core.autocrlf true

macOS 與 Linux 通常使用:

git config --global core.autocrlf input

團隊專案最好再用 .gitattributes 明確規定換行,避免每個人的全域設定不同。

建立或取得儲存庫

方法一:把現有資料夾變成 Git 儲存庫

cd C:\projects\my-app
git init
git status

git init 會建立隱藏的 .git 目錄。專案歷史、分支、標籤與本機設定都在裡面。不要手動修改 .git 內容,也不要把某個儲存庫的 .git 複製到不相關專案。

VS Code 操作:

  1. 用「檔案 → 開啟資料夾」開啟專案根目錄。
  2. Ctrl+Shift+G 開啟「原始檔控制」。
  3. 點選「初始化儲存庫」。

方法二:複製既有遠端儲存庫

git clone https://github.com/OWNER/REPOSITORY.git
cd REPOSITORY
code .

指定本機資料夾名稱:

git clone https://github.com/OWNER/REPOSITORY.git my-local-name

只下載最近一段歷史,適合非常大的儲存庫:

git clone --depth 1 https://github.com/OWNER/REPOSITORY.git

淺層複製無法直接使用完整歷史。需要補齊時執行:

git fetch --unshallow

VS Code 操作:

  1. Ctrl+Shift+P 開啟命令選擇區。
  2. 執行 Git: Clone
  3. 貼上儲存庫網址並選擇本機位置。
  4. 完成後選擇「開啟」。

方法三:在 VS Code 發布到 GitHub

本機已提交、但還沒有遠端儲存庫時,可在「原始檔控制」選擇 Publish to GitHub。依提示登入 GitHub、選擇公開或私人儲存庫,再確認要上傳的檔案。

發布前必須先檢查 .gitignore,避免把密碼、API 金鑰、私鑰、資料庫、編譯產物或大型暫存檔傳上去。

第一次完整操作

假設專案裡新增了 README.md

git status
git add README.md
git diff --staged
git commit -m "docs: add project introduction"
git log --oneline

如果已有遠端:

git push

第一次推送新分支時:

git push -u origin main

-u 會建立目前本機分支與遠端分支的追蹤關係。之後通常只要執行 git pushgit pull

VS Code 中的對應步驟:

  1. 開啟「原始檔控制」。
  2. 點選檔案,先看左右並排的差異。
  3. 按檔案旁的 +,把修改移到「已暫存的變更」。
  4. 在訊息框輸入提交說明。
  5. 按「提交」。
  6. 按「同步變更」或選單中的「推送」。

提交前先看差異,比事後補救可靠。不要把「暫存全部」當成固定習慣;每次提交只放同一目的的修改。

查看狀態與差異

git status

git status
git status --short
git status --branch --short

短格式常見代號:

代號 意義
?? 尚未追蹤的新檔案
M 已修改
A 已加入追蹤
D 已刪除
R 重新命名
UU 合併衝突尚未解決

短格式有兩欄,左欄代表暫存區,右欄代表工作目錄。例如 M 表示修改已暫存,M 表示修改尚未暫存。

git diff

git diff
git diff --staged
git diff HEAD
git diff main..feature/login
git diff --stat
git diff --word-diff
指令 比較內容
git diff 工作目錄與暫存區
git diff --staged 暫存區與目前提交
git diff HEAD 所有尚未提交的修改與目前提交
git diff A..B A 與 B 兩個位置

VS Code 會在編輯器左側顯示修改標記。點選「原始檔控制」中的檔案可開啟差異檢視;工具列能切換並排或行內顯示、上一處與下一處差異。

暫存修改

暫存指定檔案

git add src/main.py README.md

暫存目前目錄內的所有新增、修改與刪除

git add -A

互動式挑選修改區塊

git add -p

常用選項:

按鍵 用途
y 暫存目前區塊
n 不暫存目前區塊
s 把區塊拆小
e 手動編輯要暫存的內容
q 離開

VS Code 可在差異檢視中選取幾行,按右鍵選擇「暫存選取的範圍」。也能在檔案選單中選擇「暫存變更」,只暫存單一差異區塊。

取消暫存,但保留檔案修改

git restore --staged README.md

舊版教學常見 git reset HEAD README.md,效果相近;新教學使用 git restore --staged 較容易看出目的。

建立良好的提交

提交

git commit -m "fix: handle empty configuration file"

需要多段說明時:

git commit

VS Code 會開啟提交訊息編輯器,或讓你在「原始檔控制」的訊息框輸入。

提交訊息怎麼寫

第一行應說明這次修改完成了什麼,使用具體動詞,避免 updatefix stuff修改一下 這類看不出內容的文字。

fix: reject expired login tokens

Return 401 before loading the user profile and add a regression test.

團隊若採 Conventional Commits,可使用:

前綴 用途
feat: 新功能
fix: 修正錯誤
docs: 文件修改
test: 測試修改
refactor: 不改外部行為的重構
chore: 維護、工具或相依套件調整

修正最後一次提交

忘了加入檔案:

git add forgotten-file.txt
git commit --amend --no-edit

只改提交訊息:

git commit --amend

若提交已推送、其他人可能已經取得,不應任意 amend。Amend 會產生新的提交 ID,之後必須重寫遠端歷史。

.gitignore:排除不該追蹤的檔案

在儲存庫根目錄建立 .gitignore

# Python
__pycache__/
*.pyc
.venv/

# Node.js
node_modules/
dist/

# Editors and operating systems
.vscode/settings.local.json
.DS_Store
Thumbs.db

# Secrets
.env
*.pem

常見規則:

規則 效果
*.log 忽略所有 .log
build/ 忽略任何同名建置資料夾
/build/ 只忽略儲存庫根目錄的 build
temp/** 忽略 temp 下所有內容
!example.env 取消忽略 example.env

檢查某檔案被哪條規則忽略:

git check-ignore -v path\to\file

.gitignore 不會停止追蹤已經提交的檔案。要保留本機檔案、但讓 Git 停止追蹤:

git rm --cached .env
git commit -m "security: stop tracking environment file"

如果秘密曾經提交或推送,光刪檔案不夠。應立刻撤銷並更換密碼或金鑰,再評估是否需要清理歷史。

.gitattributes:統一換行與檔案行為

跨 Windows、macOS、Linux 的專案可加入:

* text=auto
*.sh text eol=lf
*.ps1 text eol=crlf
*.png binary
*.jpg binary

修改規則後重新正規化:

git add --renormalize .
git status

先檢查差異再提交,因為這次操作可能碰到大量檔案。

VS Code 原始檔控制介面

Ctrl+Shift+G 開啟「原始檔控制」。常用區域如下:

區域 功能
提交訊息框 輸入提交標題與內容
Changes/變更 尚未暫存的檔案
Staged Changes/已暫存的變更 下一次提交會包含的檔案
Merge Changes/合併變更 尚未解決的衝突
Source Control Graph 查看提交、分支、標籤與遠端關係
Timeline/時間軸 查看單一檔案的提交與本機修改歷史

圖形介面與指令對照

VS Code 操作 Git 指令概念
初始化儲存庫 git init
暫存變更 git add
取消暫存 git restore --staged
提交 git commit
捨棄變更 git restore
建立分支 git switch -c
切換分支 git switch
抓取 git fetch
提取 git pull
推送 git push
同步變更 先 pull,再 push
儲藏 git stash
合併分支 git merge

VS Code 與終端機操作同一個儲存庫,狀態會互相反映。可以用圖形介面看差異與解衝突,再用終端機執行精確指令。

命令選擇區

Ctrl+Shift+P,輸入 Git: 可找到目前可用操作,例如:

  • Git: Clone
  • Git: Initialize Repository
  • Git: Create Branch
  • Git: Checkout to
  • Git: Merge Branch
  • Git: Rebase Branch
  • Git: Fetch
  • Git: Pull
  • Git: Push
  • Git: Stash
  • Git: Add Worktree
  • Git: Show Git Output

某些項目只有在符合條件時出現。例如沒有衝突時不會顯示中止合併,未安裝 GitHub Pull Requests 擴充功能時也不會出現完整的 PR 功能。

Source Control Graph

Graph 會把提交畫成分支線,並標示本機分支、遠端分支、標籤、傳入與傳出提交。可用它確認:

  • 目前分支是否落後遠端。
  • 哪個提交建立了分支。
  • 合併是否產生 merge commit。
  • 推送前有哪些提交只存在本機。
  • 遠端新分支是否已抓到本機。

在提交上按右鍵,可依目前 VS Code 版本使用比較、建立分支、建立標籤、cherry-pick 等操作。執行前仍應確認目前分支與工作目錄狀態。

Timeline

在檔案總管選取檔案,展開下方「時間軸」。它能顯示該檔案的 Git 提交,也可納入尚未提交的本機變更。適合找出某行何時改變、比較舊版本,或在不切換整個專案的情況下查看檔案歷史。

Git 輸出紀錄

圖形介面出錯時,執行 Git: Show Git Output。這裡會顯示 VS Code 實際呼叫的 Git 指令與錯誤訊息,比只看右下角通知更容易判斷原因。

分支:把不同工作分開

分支只是指向提交的名稱,建立速度快,也不會複製整份專案。

gitGraph commit id: "A:初始版本" commit id: "B:共同基礎" branch feature/login checkout feature/login commit id: "C:登入畫面" commit id: "D:登入驗證" checkout main commit id: "E:首頁修正" merge feature/login id: "F:合併登入功能"

建立與切換分支

git branch
git branch --all
git switch -c feature/login
git switch main

從指定位置建立:

git switch -c hotfix/login v1.2.0

舊版常用 git checkout -b feature/logingit switch 專門處理分支,較不容易和還原檔案混淆。

VS Code 可點左下角狀態列的分支名稱,或執行 Git: Create BranchGit: Checkout to

重新命名與刪除分支

git branch -m old-name new-name
git branch -d feature/login
git branch -D feature/login

-d 只刪除已安全合併的分支。-D 會強制刪除,即使提交尚未合併;使用前先確認提交仍可從其他分支、標籤或 reflog 找回。

刪除遠端分支:

git push origin --delete feature/login

清除已被遠端刪除的追蹤分支:

git fetch --prune

合併分支

先切到「要接收修改」的分支,再合併來源分支:

git switch main
git pull --ff-only
git merge feature/login
git push

VS Code 操作:

  1. 切到 main
  2. 執行 Git: Merge Branch
  3. 選擇 feature/login
  4. 查看 Source Control Graph 與檔案差異。
  5. 若有衝突,解完後完成提交。

Fast-forward、merge commit 與 squash

方式 特性 常見用途
Fast-forward 直接把分支指標往前移,不新增合併提交 主分支期間沒有分岔
Merge commit 保留兩條分支的分岔與合流 想保留完整分支關係
Squash merge 把來源分支壓成一份修改再提交 功能分支有許多零碎提交

強制產生 merge commit:

git merge --no-ff feature/login

先把修改壓進暫存區,但不自動提交:

git merge --squash feature/login
git commit -m "feat: add login flow"

中止尚未完成的合併:

git merge --abort

遠端儲存庫

查看與設定遠端

git remote -v
git remote show origin
git remote add origin https://github.com/OWNER/REPOSITORY.git
git remote set-url origin git@github.com:OWNER/REPOSITORY.git
git remote rename origin github
git remote remove old-remote

origin 只是預設名稱,不是 Git 的保留字。Fork 工作流程常同時使用:

遠端 指向
origin 自己有寫入權限的 fork
upstream 原始專案
git remote add upstream https://github.com/ORIGINAL/REPOSITORY.git
git fetch upstream

Fetch、Pull、Push 的差別

sequenceDiagram participant W as 工作目錄 participant L as 本機儲存庫 participant R as 遠端儲存庫 R->>L: git fetch:只下載遠端提交 L->>W: git merge/rebase:自行決定如何整合 R->>W: git pull:fetch 後立即整合 L->>R: git push:上傳本機提交

抓取後先查看:

git fetch origin
git log --oneline --graph --decorate HEAD..origin/main
git diff HEAD..origin/main

再決定合併或 rebase:

git merge origin/main
git rebase origin/main

只接受 fast-forward,遇到分岔就停下:

git pull --ff-only

以 rebase 整合自己的本機提交:

git pull --rebase

VS Code 的「同步變更」會先 pull,再 push。若想先看遠端內容,應使用「抓取」,到 Source Control Graph 檢查後再選擇整合方式。

設定上游追蹤分支

git push -u origin feature/login
git branch -vv

若本機分支已存在:

git branch --set-upstream-to=origin/feature/login

Ahead 與 Behind

VS Code 狀態列可能顯示 ↑2 ↓1:本機有 2 個提交待推送,遠端有 1 個提交待取得。這是提交數量,不是檔案數量。

HTTPS、SSH 與登入驗證

HTTPS

多數 Git 平台不接受帳號密碼直接作為 Git 密碼。可使用瀏覽器登入、系統憑證管理員或 Personal Access Token。不要把 Token 寫進遠端網址、腳本、終端機歷史或 .env 後再提交。

檢查憑證助手:

git config --global credential.helper

Git for Windows 通常會搭配 Git Credential Manager,讓登入資料交由 Windows 安全儲存與瀏覽器授權流程處理。

SSH

產生 Ed25519 金鑰:

ssh-keygen -t ed25519 -C "[email protected]"

顯示公開金鑰:

Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub

只把 .pub 公開金鑰加入 Git 平台。沒有 .pub 副檔名的私鑰不得上傳、寄送或貼到網站。

測試 GitHub:

ssh -T git@github.com

SSH 遠端網址範例:

[email protected]:OWNER/REPOSITORY.git

處理合併衝突

當兩條歷史修改同一段內容,或一邊刪檔、另一邊改檔,Git 可能無法自動判斷應保留哪一版。

<<<<<<< HEAD
目前分支的內容
=======
要合進來的內容
>>>>>>> feature/login

VS Code 會把檔案列在「合併變更」,並提供:

  • 接受目前變更(Current)。
  • 接受傳入變更(Incoming)。
  • 接受兩者。
  • 比較兩邊差異。
  • 在三向合併編輯器中同時查看 Incoming、Current、Base 與 Result。
flowchart TD A[Git 暫停合併、rebase 或 cherry-pick] --> B[git status 查看衝突檔案] B --> C[用 VS Code 三向合併編輯器處理] C --> D[檢查 Result,刪除所有衝突標記] D --> E[執行測試與格式檢查] E --> F[git add 已解決的檔案] F --> G{目前操作} G -->|merge| H[git commit] G -->|rebase| I[git rebase --continue] G -->|cherry-pick| J[git cherry-pick --continue]

完成衝突處理

git status
git add path\to\resolved-file
git commit

Rebase 衝突則執行:

git add path\to\resolved-file
git rebase --continue

放棄操作:

git merge --abort
git rebase --abort
git cherry-pick --abort

接受 Current 或 Incoming 後仍要閱讀完整結果。兩邊都保留可能造成重複函式、重複匯入或邏輯順序錯誤;衝突標記消失只代表語法標記處理完,不代表程式正確。

把 VS Code 設成 Git 合併與差異工具

git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'

使用:

git mergetool
git difftool HEAD~1 HEAD

還原、撤銷與救援

先判斷修改在哪裡,再選指令。最危險的情況是看到錯誤就直接執行 reset --hard

flowchart TD A[想撤銷什麼?] --> B{尚未提交?} B -->|工作目錄修改| C[git restore 檔案] B -->|已暫存| D[git restore --staged 檔案] B -->|未追蹤檔| E[先 git clean -n 預覽] A --> F{已經提交?} F -->|尚未分享,只改最後一次| G[git commit --amend] F -->|已分享,要保留歷史| H[git revert 提交] F -->|本機歷史要重排| I[git rebase -i 或 git reset] A --> J{提交似乎不見了?} J --> K[git reflog 找回提交 ID]

捨棄尚未暫存的檔案修改

git restore path\to\file

還原所有已追蹤檔案:

git restore .

這會丟掉工作目錄修改。VS Code 的「捨棄變更」效果相同,按下前要看清楚檔案範圍。

從其他提交取回檔案

git restore --source=HEAD~1 path\to\file
git restore --source=main path\to\file

取回後會成為目前工作目錄的修改,仍需自行暫存與提交。

Revert:用新提交抵銷舊提交

git revert COMMIT_ID

撤銷 merge commit 時,通常要指定主要父提交:

git revert -m 1 MERGE_COMMIT_ID

Revert 適合已推送、多人共享的歷史,因為它不會刪除原提交。

Reset:移動目前分支

git reset --soft HEAD~1
git reset --mixed HEAD~1
git reset --hard HEAD~1
模式 分支指標 暫存區 工作目錄
--soft 移動 保留 保留
--mixed 移動 重設 保留
--hard 移動 重設 重設並丟棄修改

--hard 可能永久丟掉尚未提交的工作。使用前至少執行 git status、確認提交 ID,並考慮先建立暫存分支或 stash。

清理未追蹤檔案

先預覽:

git clean -n
git clean -nd

確認後才刪除:

git clean -f
git clean -fd

.gitignore 忽略的檔案預設不會刪除。git clean -fdx 連忽略檔也會刪,可能清掉 .env、相依套件與本機資料,通常不應使用。

Reflog:找回消失的提交

git reflog
git show COMMIT_ID
git switch -c rescue COMMIT_ID

Reflog 記錄本機 HEAD 與分支指標移動,常能救回誤刪分支、錯誤 reset 或 rebase 前的提交。它不是永久備份,也不會自動同步到遠端。

Stash:暫時收起未完成修改

工作做到一半,需要切換分支處理急件時:

git stash push -m "WIP: login validation"
git switch hotfix

查看與套用:

git stash list
git stash show -p 'stash@{0}'
git stash apply 'stash@{0}'
git stash pop

apply 套用後保留 stash;pop 套用成功後刪除 stash。若套用時發生衝突,先解衝突並確認工作內容,再決定是否手動刪除該 stash。

包含未追蹤檔:

git stash push -u -m "WIP: include new files"

從 stash 建立分支:

git stash branch recover-work 'stash@{0}'

VS Code 的原始檔控制選單可執行 Stash、Stash Including Untracked、Apply、Pop 與 Drop。stash 適合短期切換工作,不適合當長期備份;可理解的進度最好提交到暫存分支。

Rebase:整理本機提交基底

假設功能分支從舊的 main 分出,現在想把自己的提交接到最新 main 後方:

git fetch origin
git switch feature/login
git rebase origin/main
flowchart LR subgraph Before[Rebase 前] A1[A] --> B1[B] B1 --> C1[C:main] B1 --> D1[D:feature] D1 --> E1[E:feature] end subgraph After[Rebase 後] A2[A] --> B2[B] B2 --> C2[C:main] C2 --> D2[D'] D2 --> E2[E':feature] end

Rebase 會重播提交,因此 D、E 會變成新的 D'、E',提交 ID 也會改變。只整理自己尚未分享的提交最安全。共享分支若被改寫,其他人的歷史會分岔。

互動式 Rebase

整理最近 4 個提交:

git rebase -i HEAD~4

編輯器常見指令:

動作 用途
pick 保留提交
reword 保留內容,但修改訊息
edit 暫停,修改提交內容
squash 合併到前一個提交並編輯訊息
fixup 合併到前一個提交並丟棄本次訊息
drop 移除提交

自動暫存

工作目錄有修改時,可使用:

git rebase --autostash origin/main

它會暫時 stash 再套回,仍可能在最後產生衝突。操作前先確認 git status

Cherry-pick:挑選特定提交

把另一分支的單一提交套到目前分支:

git switch release/1.2
git cherry-pick COMMIT_ID

一次挑多個:

git cherry-pick COMMIT_A COMMIT_B

只套用修改、不立即提交:

git cherry-pick --no-commit COMMIT_ID

衝突處理:

git add resolved-file
git cherry-pick --continue
git cherry-pick --abort

Cherry-pick 會建立內容相似但 ID 不同的新提交。它適合把修正帶到維護分支,不適合取代正常的分支同步。

標籤與版本發布

建立標籤

附註標籤會保存標籤建立者、時間與訊息:

git tag -a v1.0.0 -m "Release 1.0.0"

輕量標籤:

git tag v1.0.0

替舊提交加標籤:

git tag -a v1.0.0 COMMIT_ID -m "Release 1.0.0"

查看與推送:

git tag --list
git show v1.0.0
git push origin v1.0.0
git push origin --tags

刪除本機與遠端標籤:

git tag -d v1.0.0
git push origin --delete v1.0.0

標籤通常應保持固定。若已發布的版本內容錯誤,建立新版本號比移動舊標籤更清楚。

查看提交歷史

Log

git log
git log --oneline --decorate --graph --all
git log --stat
git log -p -- path\to\file
git log --since="2 weeks ago" --author="Name"
git log --grep="login"

推薦的全域別名:

git config --global alias.lg "log --oneline --decorate --graph --all"

之後可執行:

git lg

Show

git show COMMIT_ID
git show COMMIT_ID:path/to/file
git show --name-only COMMIT_ID

Blame

git blame path\to\file
git blame -L 20,40 path\to\file

Blame 顯示每行最後由哪個提交修改。它適合追查背景,不應用來把問題直接歸咎於某個人;那行可能只是格式整理或程式搬移的結果。

VS Code 可用 Timeline 查看檔案歷史;GitLens 等第三方擴充功能能增加行內 blame 與歷史導覽,但不是使用 Git 的必要條件。

搜尋歷史與定位錯誤

搜尋目前版本的內容

git grep "searchText"
git grep -n "searchText" main

搜尋哪次提交加入或刪除字串

git log -S "functionName" --oneline
git log -G "regularExpression" -p

-S 尋找字串出現次數改變的提交,-G 尋找差異內容符合正規表示式的提交。

Bisect:二分搜尋造成錯誤的提交

git bisect start
git bisect bad
git bisect good v1.0.0

Git 會切到中間提交。測試後標記:

git bisect good

或:

git bisect bad

找到第一個壞提交後:

git bisect reset

若有可自動判斷成功或失敗的測試:

git bisect run npm test

測試程式應以結束碼 0 代表好版本,以 1127 之間的其他適當代碼代表壞版本;125 表示無法測試而跳過。

GitHub Pull Request 協作流程

典型工作順序:

flowchart LR A[同步 main] --> B[建立功能分支] B --> C[小步修改與提交] C --> D[推送分支] D --> E[建立 Pull Request] E --> F[自動測試與人工審查] F -->|要求修改| C F -->|通過| G[合併到 main] G --> H[刪除功能分支]

指令範例:

git switch main
git pull --ff-only
git switch -c feature/login

# 編輯、測試
git add -p
git commit -m "feat: add login validation"
git push -u origin feature/login

安裝 Microsoft 發布的「GitHub Pull Requests」擴充功能後,VS Code 可登入 GitHub、建立與查看 PR、閱讀討論、檢出 PR 分支、逐檔審查、留言及核准。提交與分支仍由 Git 管理,PR、Issue、審查狀態則屬於 GitHub 平台功能。

Fork 工作流程

git remote -v
git remote add upstream https://github.com/ORIGINAL/REPOSITORY.git
git fetch upstream
git switch main
git rebase upstream/main
git push origin main

功能分支推到自己的 origin,再向 upstream 專案提出 PR。

審查別人的 PR

  1. 先看 PR 說明、Issue 與自動測試結果。
  2. 逐檔閱讀差異,分辨行為變更與格式噪音。
  3. 檢查測試是否涵蓋錯誤路徑與邊界條件。
  4. 必要時在本機檢出 PR 分支並執行測試。
  5. 留言要指出檔案位置、可能後果與可驗證的修改方向。

Worktree:同時開啟多個分支

一般工作目錄一次只能檢出一個分支。Worktree 能讓同一儲存庫的不同分支位於不同資料夾,適合一邊保留開發環境,一邊處理緊急修正。

git worktree list
git worktree add ..\my-app-hotfix -b hotfix/urgent main

完成後:

git worktree remove ..\my-app-hotfix
git worktree prune

不要直接刪除 worktree 資料夾後就不處理。若資料夾已消失,使用 git worktree prune 清理記錄。

VS Code 可執行 Git: Add WorktreeGit: Open WorktreeGit: Remove Worktree。每個 worktree 可開在獨立 VS Code 視窗,終端機與執行中的開發伺服器也互不混淆。

Submodule:在專案中引用另一個儲存庫

加入子模組:

git submodule add https://github.com/OWNER/LIBRARY.git external/library
git commit -m "build: add library submodule"

複製含子模組的專案:

git clone --recurse-submodules https://github.com/OWNER/PROJECT.git

已經 clone 後再初始化:

git submodule update --init --recursive

更新到子模組遠端所追蹤的版本:

git submodule update --remote --merge

父專案記錄的是子模組提交 ID,不是子模組全部內容。修改子模組時,要先在子模組內提交與推送,再回父專案提交新的指標。團隊若不需要獨立版本與權限,普通套件管理或直接放在同一儲存庫通常更省事。

Git LFS:管理大型二進位檔

Git 不擅長頻繁修改的大型二進位檔。Git LFS 會讓 Git 儲存小型指標,實際內容放在 LFS 伺服器。

安裝後初始化:

git lfs install
git lfs track "*.psd"
git lfs track "*.zip"
git add .gitattributes
git add assets\design.psd
git commit -m "assets: add design source through Git LFS"

查看追蹤狀態:

git lfs track
git lfs ls-files

先確認遠端平台的 LFS 容量、流量限制與費用。把既有大型檔案改成 LFS 可能需要重寫歷史,不能只新增一條 track 規則就期待舊提交縮小。

簽署提交與標籤

Git 可使用 GPG 或 SSH 金鑰簽署提交,讓平台驗證提交與標籤來源。團隊應先統一採用哪種方式,再設定自動簽署。

查看簽署狀態:

git log --show-signature
git verify-commit COMMIT_ID
git verify-tag v1.0.0

簽署能證明提交由持有對應私鑰的人產生,不能證明程式安全或審查完整。私鑰仍需妥善保護並設定撤銷方式。

Git Hooks 與自動檢查

Hooks 是特定 Git 事件發生時執行的腳本,例如提交前格式檢查或推送前測試。儲存庫本機 hooks 位於 .git/hooks,預設不會被 Git 追蹤。

常見 hooks:

Hook 時機 用途
pre-commit 建立提交前 格式、lint、秘密掃描
commit-msg 讀取提交訊息後 檢查訊息格式
pre-push 推送前 執行測試
post-merge 合併後 更新相依套件或提示

團隊可把腳本放入專案,例如 .githooks/,再設定:

git config core.hooksPath .githooks

本機 hook 能用 --no-verify 略過,不能當作唯一安全防線。必要檢查仍應放入 CI 與伺服器端分支保護。

常用設定與別名

推送與抓取

git config --global push.autoSetupRemote true
git config --global fetch.prune true
git config --global pull.ff only

pull.ff only 會讓 pull 遇到分岔時停止,要求使用者明確選 merge 或 rebase。若團隊規定一律 rebase,可改設 pull.rebase true,不要同時套用互相衝突的政策。

Rerere:重用衝突解法

git config --global rerere.enabled true

Rerere 會記錄你如何解決某組衝突。之後 rebase 或反覆合併遇到相同衝突時,Git 可重用解法;套用後仍要檢查與測試。

實用別名

git config --global alias.st "status --short --branch"
git config --global alias.last "log -1 --stat"
git config --global alias.unstage "restore --staged --"
git config --global alias.lg "log --oneline --decorate --graph --all"

別名應保持短小明確。不要把 push --forcereset --hard 等破壞性操作藏在難以辨識的別名裡。

VS Code 建議設定

在設定介面搜尋 git,可依工作習慣調整:

設定 用途 建議
git.autofetch 背景抓取遠端狀態 常用遠端協作時開啟
git.autofetchPeriod 自動抓取間隔秒數 不必設得過短
git.pruneOnFetch 抓取時清理消失的遠端分支 可開啟
git.confirmSync 同步前詢問 初學者保留開啟
git.enableSmartCommit 沒有暫存內容時直接提交所有變更 建議關閉或謹慎使用
git.openRepositoryInParentFolders 是否尋找父資料夾中的儲存庫 多儲存庫工作區要留意範圍

設定範例:

{
  "git.autofetch": true,
  "git.autofetchPeriod": 180,
  "git.pruneOnFetch": true,
  "git.confirmSync": true,
  "git.enableSmartCommit": false
}

設定名稱可能隨 VS Code 版本增加或調整。可直接在設定介面搜尋並閱讀目前版本顯示的說明。

多儲存庫與工作區

VS Code 工作區可能同時包含前端、後端與文件等多個 Git 儲存庫。「原始檔控制」上方可切換儲存庫。提交前確認:

  • 訊息框屬於哪個儲存庫。
  • 目前分支名稱。
  • 暫存檔案是否跨到另一個 repo。
  • 終端機目前位於哪個路徑。

終端機可執行:

git rev-parse --show-toplevel
git status --short --branch

第一個指令會顯示目前 Git 儲存庫根目錄。

Detached HEAD 是什麼

直接切到提交或標籤時,HEAD 可能不在分支上:

git switch --detach v1.0.0

這適合唯讀檢查舊版本。若在 detached HEAD 建立了想保留的提交,立刻建立分支:

git switch -c investigation/result

若已離開該提交,可用 git reflog 找回。

強制推送的安全界線

Rebase、amend 或 reset 後,本機與遠端歷史可能不同。確定要更新自己專用的遠端分支時,使用:

git push --force-with-lease

--force-with-lease 會在遠端分支不是你最後看過的狀態時拒絕推送,能避免直接覆蓋別人剛推送的提交。它仍會重寫歷史,不能視為一般 push。

不要對多人共用的 maindevelop、發布分支使用強制推送。平台應啟用分支保護、PR 審查與必要狀態檢查。

常見工作流程

個人小型專案

git status
git add -p
git commit -m "描述這次修改"
git pull --rebase
git push

即使只有一個人,也建議功能較大時開分支,讓 main 保持可執行狀態。

團隊功能分支

git switch main
git pull --ff-only
git switch -c feature/short-name

# 完成一組可測試的修改
git add -p
git commit -m "feat: ..."
git push -u origin feature/short-name

接著建立 PR,讓 CI 與成員審查,通過後再合併。

緊急修正

git switch main
git pull --ff-only
git switch -c hotfix/issue-name

完成修正與測試後提交、推送並建立 PR。若同時維護舊版本,可把修正提交 cherry-pick 到對應發布分支。

不建議長期維持的做法

  • 所有人直接在 main 開發並推送。
  • 一次提交混合功能、格式整理、套件升級與大量重新命名。
  • 每次 pull 都不看內容就解衝突。
  • 把 stash 當成長期版本歷史。
  • 對共用分支持續強制推送。
  • .env、私鑰、憑證或資料庫備份提交到 Git。

常見錯誤與處理方式

fatal: not a git repository

目前路徑不在 Git 儲存庫內。

Get-Location
Get-ChildItem -Force
git rev-parse --show-toplevel

切到正確專案,或確認是否尚未執行 git initgit clone

Author identity unknown

設定姓名與信箱:

git config --global user.name "你的名字"
git config --global user.email "[email protected]"

nothing to commit

可能沒有修改、檔案被忽略,或修改已提交。檢查:

git status
git diff
git check-ignore -v path\to\file

non-fast-forward 或推送被拒絕

遠端已有本機沒有的提交。先抓取與查看:

git fetch origin
git log --oneline --graph --decorate --all

再依團隊規則選擇:

git pull --rebase

或:

git merge origin/main

不要在沒看差異時改用 git push --force

Need to specify how to reconcile divergent branches

本機與遠端都新增了提交,Git 要求選擇 pull 策略。本次可明確指定:

git pull --rebase
git pull --no-rebase
git pull --ff-only

再依團隊規則設定全域或專案預設。

Your local changes would be overwritten

Git 為了避免覆蓋未提交修改而停止。可選擇提交、stash,或確認不要後還原:

git status
git stash push -u -m "WIP before switching"

Merge/Rebase 一直無法完成

先看目前狀態:

git status

Git 會列出未解衝突檔案與下一步。處理完要 git add;rebase 再執行 git rebase --continue。想回到操作前則用相對應的 --abort

index.lock 已存在

先確認沒有 Git、VS Code、IDE 或套件管理程序仍在操作該儲存庫。若所有 Git 程序都已結束,而且錯誤仍存在,才考慮移除 .git/index.lock。不要在 Git 正在執行時刪除鎖定檔。

detected dubious ownership

Git 認為儲存庫擁有者與目前使用者不一致。先檢查資料夾來源與權限,確定可信後才加入:

git config --global --add safe.directory C:/path/to/repository

不要把 * 設成全部信任,否則會失去這項保護。

大量出現 CRLF/LF 修改

檢查:

git config --show-origin --get core.autocrlf
git check-attr -a -- path\to\file

先和團隊確認 .gitattributes 規則,再用 git add --renormalize . 統一。不要把真正程式修改和全專案換行變更塞進同一提交。

VS Code 沒有顯示 Git 變更

  1. 執行 git status,判斷問題在 Git 或 VS Code。
  2. 確認 VS Code 開啟的是儲存庫根目錄或其子目錄。
  3. 執行 Git: Show Git Output
  4. 確認內建 Git 擴充功能沒有被停用。
  5. 重新載入視窗:Developer: Reload Window
  6. 檢查設定中的 Git Path 是否指到有效的 git.exe

HTTPS 驗證失敗

確認遠端網址與帳號權限:

git remote -v

清除或更新作業系統憑證管理員中的舊憑證,再重新觸發瀏覽器登入。不要把帳號密碼直接寫進網址。

SSH Permission denied (publickey)

ssh -vT git@github.com
git remote -v

檢查使用的遠端是否為 SSH 格式、公開金鑰是否加入正確帳號、私鑰是否由 ssh-agent 或 SSH 設定找到。-v 輸出可能含主機與本機路徑,分享除錯紀錄前先遮蔽敏感資料。

每次提交前的檢查表

  • git status 顯示的儲存庫與分支正確。
  • git diffgit diff --staged 已閱讀。
  • 沒有密碼、Token、私鑰、個資或不必要的大型檔案。
  • 本次提交只處理同一目的。
  • 測試、格式檢查與建置已依專案要求通過。
  • 提交訊息能讓半年後的自己看懂。
  • 推送前已確認遠端的新提交與分支保護規則。

指令速查表

目的 指令
查看狀態 git status --short --branch
查看未暫存差異 git diff
查看已暫存差異 git diff --staged
暫存檔案 git add FILE
逐區塊暫存 git add -p
取消暫存 git restore --staged FILE
提交 git commit -m "message"
修正最後提交 git commit --amend
查看圖形歷史 git log --oneline --decorate --graph --all
建立並切換分支 git switch -c BRANCH
切換分支 git switch BRANCH
合併分支 git merge BRANCH
抓取遠端 git fetch --prune
提取並 rebase git pull --rebase
推送新分支 git push -u origin BRANCH
暫時收起修改 git stash push -u -m "message"
套用 stash git stash apply 'stash@{0}'
用新提交撤銷舊提交 git revert COMMIT
找回指標歷史 git reflog
挑選提交 git cherry-pick COMMIT
建立版本標籤 git tag -a v1.0.0 -m "Release 1.0.0"
查看儲存庫根目錄 git rev-parse --show-toplevel

建議練習

在不重要的測試資料夾建立儲存庫,依序完成以下練習:

  1. 建立三個檔案,只暫存其中兩個並提交。
  2. 修改同一檔案的兩個不同區塊,用 git add -p 只提交其中一區。
  3. 建立功能分支,分別在 main 與功能分支提交,再合併。
  4. 刻意讓兩條分支修改同一行,用 VS Code 三向合併編輯器解衝突。
  5. 建立錯誤提交,用 git revert 撤銷。
  6. git reset --soft HEAD~1 拆回最後提交,再重新整理提交內容。
  7. 刪除測試分支後,從 git reflog 找到提交並建立救援分支。
  8. 建立第二個 worktree,同時在兩個 VS Code 視窗開啟不同分支。

所有破壞性練習都應放在測試儲存庫。熟悉 statusdifflogreflog 後,再處理真正專案的歷史。

官方參考資料