Git 完整教學:從指令列到 VS Code 圖形介面
Git 用來記錄檔案的版本、比較修改、建立分支、合併成果,也能和 GitHub、GitLab、Bitbucket 或自架伺服器協作。本篇從第一次安裝開始,逐步說明日常開發、VS Code 操作、遠端同步、衝突處理、版本回復與進階工具。
本文以 Windows 與 VS Code 為主要示範環境。Git 指令在 macOS、Linux 上大致相同;畫面名稱可能因 VS Code 版本與語言設定略有差異。
本文最後更新於 2026 年 8 月 28 日。若只想完成第一次提交,可先讀「第一次完整操作」;遇到問題時,再從目錄跳到對應章節。
目錄
展開目錄
- Git 完整教學:從指令列到 VS Code 圖形介面
- 目錄
- 先看懂 Git 在記錄什麼
- 安裝 Git 與 VS Code
- 第一次設定 Git
- 建立或取得儲存庫
- 第一次完整操作
- 查看狀態與差異
- 暫存修改
- 建立良好的提交
- .gitignore:排除不該追蹤的檔案
- .gitattributes:統一換行與檔案行為
- VS Code 原始檔控制介面
- 分支:把不同工作分開
- 合併分支
- 遠端儲存庫
- HTTPS、SSH 與登入驗證
- 處理合併衝突
- 還原、撤銷與救援
- Stash:暫時收起未完成修改
- Rebase:整理本機提交基底
- Cherry-pick:挑選特定提交
- 標籤與版本發布
- 查看提交歷史
- 搜尋歷史與定位錯誤
- GitHub Pull Request 協作流程
- Worktree:同時開啟多個分支
- Submodule:在專案中引用另一個儲存庫
- Git LFS:管理大型二進位檔
- 簽署提交與標籤
- Git Hooks 與自動檢查
- 常用設定與別名
- VS Code 建議設定
- 多儲存庫與工作區
- Detached HEAD 是什麼
- 強制推送的安全界線
- 常見工作流程
- 常見錯誤與處理方式
- fatal: not a git repository
- Author identity unknown
- nothing to commit
- non-fast-forward 或推送被拒絕
- Need to specify how to reconcile divergent branches
- Your local changes would be overwritten
- Merge/Rebase 一直無法完成
- index.lock 已存在
- detected dubious ownership
- 大量出現 CRLF/LF 修改
- VS Code 沒有顯示 Git 變更
- HTTPS 驗證失敗
- SSH Permission denied (publickey)
- 每次提交前的檢查表
- 指令速查表
- 建議練習
- 官方參考資料
先看懂 Git 在記錄什麼
Git 不只是把檔案複製成多份備份。每次提交(commit)都會記錄當時的專案快照、作者、時間、說明文字,以及上一個提交的位置。多數 Git 操作都在本機完成,沒有網路也能提交、切換分支與查看歷史。
一份 Git 專案通常會遇到以下區域:
| 區域 | 英文名稱 | 用途 |
|---|---|---|
| 工作目錄 | Working tree | 實際正在編輯的檔案 |
| 暫存區 | Staging area/Index | 挑選「下一次提交要包含哪些修改」 |
| 本機儲存庫 | Local repository | 儲存在 .git 裡的提交與分支歷史 |
| 遠端儲存庫 | Remote repository | GitHub、GitLab 或伺服器上的協作副本 |
git add 的作用是挑選下一次提交的內容,不等於上傳。git commit 只寫入本機歷史,git push 才會把本機提交送到遠端。
常見名詞
| 名詞 | 說明 |
|---|---|
| Repository/repo | Git 儲存庫,包含專案檔案與 .git 歷史資料 |
| Commit | 一次有說明文字的版本快照 |
| Branch | 指向某個提交的可移動名稱,例如 main、feature/login |
| HEAD | 目前所在的提交,通常會跟著目前分支移動 |
| Remote | 指向另一份儲存庫的名稱,最常見的是 origin |
| Clone | 複製遠端儲存庫及其歷史到本機 |
| Fetch | 下載遠端新歷史,但不改目前工作檔案 |
| Pull | 先抓取,再把遠端變更整合到目前分支 |
| Push | 把本機提交送往遠端 |
| Merge | 合併兩條分支的歷史 |
| Rebase | 把一串提交改接到另一個基底上 |
| Tag | 固定指向特定提交的標記,常用於版本號 |
安裝 Git 與 VS Code
Windows
- 從 Git 官方網站 安裝 Git for Windows。
- 從 VS Code 官方網站 安裝 Visual Studio Code。
- 安裝 Git 時若不確定選項,可保留預設值。預設編輯器之後仍能改成 VS Code。
- 安裝完成後重開 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 操作:
- 用「檔案 → 開啟資料夾」開啟專案根目錄。
- 按
Ctrl+Shift+G開啟「原始檔控制」。 - 點選「初始化儲存庫」。
方法二:複製既有遠端儲存庫
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 操作:
- 按
Ctrl+Shift+P開啟命令選擇區。 - 執行
Git: Clone。 - 貼上儲存庫網址並選擇本機位置。
- 完成後選擇「開啟」。
方法三:在 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 push 與 git pull。
VS Code 中的對應步驟:
- 開啟「原始檔控制」。
- 點選檔案,先看左右並排的差異。
- 按檔案旁的
+,把修改移到「已暫存的變更」。 - 在訊息框輸入提交說明。
- 按「提交」。
- 按「同步變更」或選單中的「推送」。
提交前先看差異,比事後補救可靠。不要把「暫存全部」當成固定習慣;每次提交只放同一目的的修改。
查看狀態與差異
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 會開啟提交訊息編輯器,或讓你在「原始檔控制」的訊息框輸入。
提交訊息怎麼寫
第一行應說明這次修改完成了什麼,使用具體動詞,避免 update、fix 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: CloneGit: Initialize RepositoryGit: Create BranchGit: Checkout toGit: Merge BranchGit: Rebase BranchGit: FetchGit: PullGit: PushGit: StashGit: Add WorktreeGit: 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 指令與錯誤訊息,比只看右下角通知更容易判斷原因。
分支:把不同工作分開
分支只是指向提交的名稱,建立速度快,也不會複製整份專案。
建立與切換分支
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/login。git switch 專門處理分支,較不容易和還原檔案混淆。
VS Code 可點左下角狀態列的分支名稱,或執行 Git: Create Branch、Git: 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 操作:
- 切到
main。 - 執行
Git: Merge Branch。 - 選擇
feature/login。 - 查看 Source Control Graph 與檔案差異。
- 若有衝突,解完後完成提交。
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 的差別
抓取後先查看:
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。
完成衝突處理
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。
捨棄尚未暫存的檔案修改
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
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 代表好版本,以 1 到 127 之間的其他適當代碼代表壞版本;125 表示無法測試而跳過。
GitHub Pull Request 協作流程
典型工作順序:
指令範例:
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
- 先看 PR 說明、Issue 與自動測試結果。
- 逐檔閱讀差異,分辨行為變更與格式噪音。
- 檢查測試是否涵蓋錯誤路徑與邊界條件。
- 必要時在本機檢出 PR 分支並執行測試。
- 留言要指出檔案位置、可能後果與可驗證的修改方向。
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 Worktree、Git: Open Worktree 與 Git: 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 --force、reset --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。
不要對多人共用的 main、develop、發布分支使用強制推送。平台應啟用分支保護、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 init/git 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 變更
- 執行
git status,判斷問題在 Git 或 VS Code。 - 確認 VS Code 開啟的是儲存庫根目錄或其子目錄。
- 執行
Git: Show Git Output。 - 確認內建 Git 擴充功能沒有被停用。
- 重新載入視窗:
Developer: Reload Window。 - 檢查設定中的 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 diff與git 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 |
建議練習
在不重要的測試資料夾建立儲存庫,依序完成以下練習:
- 建立三個檔案,只暫存其中兩個並提交。
- 修改同一檔案的兩個不同區塊,用
git add -p只提交其中一區。 - 建立功能分支,分別在
main與功能分支提交,再合併。 - 刻意讓兩條分支修改同一行,用 VS Code 三向合併編輯器解衝突。
- 建立錯誤提交,用
git revert撤銷。 - 用
git reset --soft HEAD~1拆回最後提交,再重新整理提交內容。 - 刪除測試分支後,從
git reflog找到提交並建立救援分支。 - 建立第二個 worktree,同時在兩個 VS Code 視窗開啟不同分支。
所有破壞性練習都應放在測試儲存庫。熟悉 status、diff、log 與 reflog 後,再處理真正專案的歷史。