# 🧙‍♀️\ 我要成為 Git 大師!/📘 Git 筆記總覽 v1.0|第一章 ## 一、 Git的本質是什麼?用途是什麼? ### 🔍 Git 是什麼? Git 是一套「分散式版本控制系統(DVCS)」 用來記錄每一次檔案的變更狀態、管理歷史紀錄,並支援多人協作與分支開發。 它不是單純幫你儲存檔案,而是幫你記錄: - 你每一次對專案的改動 - 每一筆改動的原因(訊息) - 改的是什麼(內容差異) - 是誰改的、什麼時候改的 - 這份改動該不該合併進主線(分支管理) ##### 📌 語感比喻: Git = 存檔記錄員 + 時間旅行員 + 平行宇宙管理員 ### 📌 Git 解決了哪些問題? #### 🚨 傳統沒 Git 會遇到什麼慘事? 傳統做法會遇到: - 改錯檔案、想復原卻沒備份 😵 - 不知道誰改了什麼、改在哪裡 - 多人合作時,覆蓋來覆蓋去亂七八糟 - 想要同時開發多個版本(例如新功能、bug 修正)沒辦法區隔 ##### Git 的解法: | 痛點 | Git 的對應設計 | | -------- | --------------------------------- | | 改錯想復原 | `commit` + `log` + `revert/reset` | | 不知道改了什麼 | `diff` + `status` + `blame` | | 多人合作亂套 | 分支管理 + 遠端同步機制 | | 多版本同步與整合 | `branch` + `merge` + `rebase` | #### ☁️ 和「儲存檔案 / 雲端備份」的差別? 那 Git 到底跟我們熟悉的「雲端同步工具」有什麼根本差別呢? | 類型 | 儲存方式 | 記錄歷史? | 分支支援? | 協作方式 | | --------- | ------------ | ----- | ----- | -------------------- | | 🗃 傳統檔案儲存 | 覆蓋原檔案 | ❌ | ❌ | 手動傳檔案 | | ☁️ 雲端備份 | 自動同步到雲端 | ✅(有限) | ❌ | 雲端同步(如 Google Drive) | | 🧙 Git | 版本快照+分支+同步系統 | ✅✅✅ | ✅✅✅ | 遠端同步+多人版本控制 | ▸ Git 的強大之處是它「不只是備份」,而是: ▸ 每次 commit 都是一份完整狀態的快照 ▸ 每個分支都能平行改進、測試、還原 ▸ 每個人都有一份完整的歷史紀錄(即使離線) ##### Git = 不只是備份,是一整套「版本管理機制」。 #### 👤 單人 vs 👥 團隊的價值差異 ##### 【單人使用】 - 改壞了 → reset 回上一版 - 想記錄「為什麼這樣改」→ commit message - 想試兩種做法 → 開 branch 各自實驗 ##### 【多人協作】 - 一人一條 branch,互不干擾。每個人可以在自己的分支上開發,合併時才整合。 - 有明確的歷史紀錄,知道誰改了什麼 - 開 issue / PR / code review 有依據、有版本可回頭比對 - Git 是團隊開發的「時間、行為與責任的紀錄系統」 #### 🧠 總結語感 Git 不是存檔,而是記錄每一次「決策快照」的系統。 ▸ 每次你下 `commit`,就像拍了一張完整快照,標記了「誰、什麼時候、改了什麼、為什麼要改」。 它讓你的專案不只是持續前進, ▸ 而是能夠——分歧、比較、整合、還原、討論、同步。 ✅ 單人開發:自我備份、自我反省、自我實驗 ✅ 團隊協作:角色分工、歷史可查、風險可控 #### 📎所以Git是什麼? ——🧾 Git是專案的「記錄秘書」: ▸ 幫你紀錄每一次重要改動(commit) ▸ 幫你寫好改動說明(message) ▸ 幫你標好是哪個人(作者) ▸ 幫你整理出來一份改版歷史年表(log) ——🎞️ 專案的「時間導演」: ▸ 可以讓你回到過去看舊版本(reset / checkout) ▸ 可以選擇一條分支走不同劇情(branch) ▸ 最後再把大家演過的版本合併成主線劇情(merge / rebase) ——🧬 專案的「分身系統」: ▸ 你可以同時開發多個方向,互不干擾(分支) ▸ 每個人都可以有自己的版本,最終再對齊(協作流程) ##### 所以如果你要一句話定義 Git: 💬 「Git 是一個專案的版本記錄員兼平行宇宙管理者。」 → 每一個變更都能被記錄、還原、分岔與合併。 ## 二、Git 重要概念:三大空間 × 為什麼要這樣設計? ### 🔍 什麼是「三大空間」? Git 為了讓你在「開發」與「記錄歷史」之間擁有彈性控制,它把版本控制流程切分成三個空間: 1️⃣ Working Directory(工作區) → 你正在電腦裡編輯的檔案(VSCode 開著的就是它) 2️⃣ Staging Area(暫存區) → 你選擇「準備記錄」的改動(用 `git add` 放進來) 3️⃣ Repository(儲存庫) → 真正被記錄下來的歷史版本(你每次 `commit` 就會新增一筆) ### 🪄三大空間資料流動的方向 📦 檔案會怎麼流動?用什麼指令代表進出哪一區? | 操作目標 | 使用的 Git 指令 | 對應的空間變化 | | ---------------------- | -------------------- | ---------------------- | | 查看三區整體狀態 | `git status` | 顯示工作區 vs 暫存區、哪些有變動 | | 編輯檔案(VSCode、IDE) | (直接操作,不需 Git 指令) | 工作區內容發生變動 | | 加入清單(準備提交) | `git add <檔名>` / `.` | 工作區 → 暫存區 | | 正式記錄變更(建立版本) | `git commit -m "訊息"` | 暫存區 → 儲存庫(建立一個 commit) | | 查看歷史(誰改過什麼) | `git log` | 查看儲存庫歷史紀錄 | | 丟掉未 add 的變動(還原) | `git checkout <檔名>` | 從儲存庫把該檔案狀態拉回來 → 覆蓋工作區 | | 丟掉已 add 但尚未 commit 的清單 | `git reset <檔名>` | 把暫存區的變更退回工作區 | #### 📌 記得! git add 就像把變更 塞進一張待送的表單 git commit 就像按下「送出」讓它 變成正式記錄的一頁 #### 【示意圖】 🖥️ 工作區(Working Directory) ↓ git add 📥 暫存區(Staging Area) ↓ git commit 🗃️ 儲存庫(Repository / HEAD) #### 👇正常開發流程會這樣跑: 1. 你在工作區改檔案  → 這是你在 VSCode 打字的地方。Git 還沒記錄這些改動。 2. 你用 git add 把改好的檔案加入暫存區  → 代表你說:「這些改動我覺得 OK,可以記錄下來。」 3. 你用 git commit 正式提交成一版  → Git 把這些檔案存成一個快照,加入歷史版本(儲存庫) ### 📌 這樣設計的意義是什麼? 🔄如果資料改了,但你沒 add 或 commit,會怎樣? | 狀況 | 發生在哪裡 | Git 狀態 | | -------------- | ------- | ------------------ | | 改了檔案但沒 add | 工作區 | Git 看到檔案有改,但還沒入清單 | | add 了但沒 commit | 暫存區 | Git 暫存了清單,但還沒變成歷史 | | commit 了 | 儲存庫 | 改動正式進入版本紀錄 | | 又再度編輯某檔案 | 工作區再次更新 | 該檔案在三層中會變成「和上一版不同」 | #### 💬 如果只有一層會怎樣? → 你改了檔案,Git 就立刻記下來,那你會: - 沒空間做「中間決定」 - 無法「只提交其中一部分」 - 失去版本控制的彈性與精細程度 #### ✅ 三層設計的好處: | 空間 | 負責什麼? | 使用時機 | |--------------|----------------------|---------------------------------------------| | 工作區 | 實際在寫的檔案 | 我在寫 code,但還不確定要不要提交 | | 暫存區 | 提交前的候選變更清單 | 我挑好要提交的部分,但還沒正式變成版本 | | 儲存庫(HEAD) | 已經 commit 的歷史版本 | 我正式提交的東西,每次都變成 Git 記錄的一頁歷史 | ### 🧪 CLI × 三大空間對應指令: 💡舉例! 1. 只想還原某檔案到上一次 commit 狀態?你需要從「儲存庫」 → 拉回「工作區」版本 - 指令:git checkout 檔名(還原) 2. 想知道哪些改了還沒 commit?你需要看「工作區 vs 暫存區」差異 - 指令:git diff 3. 想知道哪些準備要被 commit 了?你要看「暫存區 vs 儲存庫」的差異 - 指令:git diff --cached #### 【開發現場流程圖】 ✍️ 改檔案(VSCode 改了一堆) ← 工作區 ↓ git add 📝 放進清單 → 等待被提交 ← 暫存區 ↓ git commit 📚 記錄成一版 → 留下歷史快照 ← 儲存庫(HEAD) | 你想做的事 | 指令 | 發生在哪一層? | |------------------------------|-----------------------------------|------------------------| | 查看目前改了哪些 | `git status` | 看 工作區 和 暫存區 差異 | | 把改動放進暫存區 | `git add .` / `git add <file>` | 從工作區 → 暫存區 | | 提交變更成一個版本 | `git commit -m "訊息"` | 從暫存區 → 儲存庫 | | 看你 commit 過什麼 | `git log` | 查看 儲存庫歷史 | | 還原某檔案成上一次儲存版本狀態 | `git checkout <file>` | 把 儲存庫 → 工作區 | | 比較工作區和暫存區的差異 | `git diff` | 工作區 vs 暫存區 | | 比較暫存區和儲存庫(最新 commit) | `git diff --cached` / `--staged` | 暫存區 vs 儲存庫 | #### 🧠 總結語感: Git 透過三層結構讓你擁有「選擇權」。 你想記哪些改動、什麼時候記、怎麼分階段記,都可以自己控制。 多這兩層(暫存區+儲存庫),就是為了安全感 × 可控性 × 清晰歷史。 ## 三、雲端與本地端 (待補充) ## 四、 使用情境 × 語法(功能分類) 📦 這章的核心目的是: 「把 Git 的實際操作拆成任務情境,再對應需要用到的語法。」 ### 功能分類總表 | 功能分類 | 常見操作行為 | 對應 Git 指令群 | | --------- | ----------------------- | ------------------------------------------------------ | | 🗂️ 專案初始化 | 開始使用 Git 管理一個資料夾 | `git init`, `git clone`, `.gitignore` | | 📜 版本控制 | 記錄每次改動、查看紀錄、建立說明 | `git add`, `git commit`, `git status`, `git log` | | 🔀 分支管理 | 開新分支、切換、合併、重整 | `git branch`, `git checkout`, `git merge`, `rebase` | | 🔄 遠端同步 | 推上 GitHub、拉別人改動、與遠端連結 | `git remote`, `git push`, `git pull`, `git fetch` | | 🛠️ 修復還原 | 回退錯誤、還原檔案、暫存未完成改動 | `git reset`, `git revert`, `git stash`, `git checkout` | | 🧹 歷史整理 | 編輯、合併、刪減 commit,讓歷史紀錄乾淨 | `git rebase -i`, `commit --amend`, `tag`, `fixup` | | 🧬 進階管理 | 拆模組、套 patch、用 hook 自動化 | `submodule`, `format-patch`, `git hook` | --- ### 📂 專案初始化 × 建立 Git 管理環境 🎯 當你想要 ——「讓這個資料夾開始被 Git 管理」 (也就是從零建立 Git 管理環境,或是從別人那邊抓專案回來) 你會遇到兩種情境: 1️⃣ 我是自己開始一個專案(init) 2️⃣ 我是從 GitHub 或遠端拉回來(clone) #### 🧪【情境一】自己開一個新 Git 專案 ##### 📌 操作流程: ``` cd 【專案資料夾】 git init ``` ##### 📎 語感翻譯: > `git init` :把git放進去 > 從這刻開始你每次 `commit` 都會被記進這本筆記本裡(`.git` 資料夾) 🔍 裡面會出現 `.git` 隱藏資料夾,這就是 Git 的內部腦袋 **不要亂刪!亂刪會讓 Git 忘記它自己是誰。** #### 🧪【情境二】從 GitHub / 遠端抓一個現成專案 ##### 📌 操作流程: ``` git clone 【github儲存庫】 ``` ##### 📎 語感翻譯: `git clone` :把這個儲存庫載下來 網址是github儲存庫, 你會拿到: - 所有檔案 - 所有 commit 歷史 - Git 已經幫你 init 好、remote 也設定好(origin) ##### 🧤 其他補充: ###### 📌 `.gitignore`:在你 `init` 之後,可以設定「哪些檔案不要記錄」 ``` node_modules/ .env .DS_Store ``` Git 會自動忽略這些項目,不加入版本管理。 ###### 📌 `.git` 是 Git 的核心資料夾(會被隱藏) 裡面記得的東西有: - HEAD 指向的位置 - commit 紀錄 - 你的分支結構 - 遠端來源(remote) #### 🧠 總結語感: | 我要做的事 | 指令 | 發生的變化 | |--------------------|---------------------------|----------------------------------| | 自己新建一個 Git 專案 | `git init` | 建立 `.git` 目錄(開始版本管理) | | 複製別人的 Git 專案 | `git clone <網址>` | 拿到檔案+歷史紀錄+remote 設定 | | 設定忽略的檔案 | `.gitignore` 檔案 | 被列入的檔案不會被 `add` 追蹤 | Git 管理的不是「檔案」本身,而是「你對這個資料夾的一連串改動歷程」。 >`init` 是你讓 Git 開始「看見一切」的起點。 --- ### 📜 版本控制 × 記錄每一次改動的歷史 🎯 當你想要 ——「讓某次修改被記錄下來,留在專案歷史中」 這是一個最常見的日常循環流程:  改了東西 → 想記錄 → 選好哪些要記錄 → 寫說明 → 存進歷史版本 #### 🪄 Git 的版本控制流程順序(基本三部曲): 1️⃣ 改檔案(VSCode 裡動手) 2️⃣ `git add` → 把改動選進「準備提交清單」 3️⃣ `git commit -m "我改了什麼"` → 正式打進歷史紀錄 #### 📦 指令清單與語感說明: | 操作目標 | Git 指令 | 語感翻譯 | |------------------|------------------------------------|----------------------------------------------------| | 查看目前改了哪些 | `git status` | 幫你看出目前有哪些檔案「有動過、沒被提交」 | | 加入待提交清單 | `git add <檔名>` / `git add .` | 把改動「打勾」說:這些我準備要提交 | | 提交成一個版本點 | `git commit -m "說明內容"` | 正式寫進歷史紀錄本,附上一段說明 | | 查看所有版本歷史 | `git log` / `git log --oneline` | 翻出你以前寫過的所有版本,每一次 `commit` 就是一頁 | #### 📘 範例流程: ``` (你改了 index.html) git status git add index.html git commit -m "調整首頁標題樣式" ``` 結果會新增一筆歷史記錄(commit),並把這次改動永久記下來。 #### 📎 補充語感小知識: 1. `add` 就像在準備一個便當:你把你要交的內容裝進盒子(暫存區) 2. `commit` 就是蓋章、密封、送出,這一版就變成歷史快照 3. `log` 是你的 commit 歷史清單,裡面會寫上: - commit 編號(SHA) - 作者 - 時間 - 提交訊息 #### 🧯 常見錯誤: | 狀況 | 解法與建議 | |----------------------------------|----------------------------------------| | `commit` 完才發現沒 `add` 某檔案 | 再 `add` → `commit --amend` 修改上次提交 | | 寫錯訊息想改 | `git commit --amend` 可重新寫 message | | 忘記加檔名 → 只打 `git add` 沒效果 | 用 `git add .` 或具體檔案名 | | 不小心 `add` 錯檔案 | `git reset <檔名>` 把它退回工作區 | #### 🧠 總結語感: 每一次 `commit` 都是幫你記下「我這次做了什麼事、為什麼這樣做」的快照。 長遠來看,`log` 就是你的**學習歷史、協作紀錄、產品成長日記**。 ✅ Git 不會「自動幫你記住你做了什麼」,你要自己決定: - 哪些要記(add) - 什麼時候記(commit) - 要不要寫得好一點(訊息) --- ### 🔀 分支管理 × 開新世界、切來切去、再合併成主線 🎯 當你想要 ——「同一份專案同時開發多個方向,不影響主線版本」 這時候你就會使用 Git 的強大系統功能:「分支(branch)」 #### 📌 為什麼要有分支? 想像你現在正在開發一個網頁, 突然 PM 跑過來說:「可以試試看新增一個夜間模式嗎?」 👉 你不會直接在主線亂改, 你會:**開一條新的分支,先試試看,等穩定再合併回去。** #### 🪄 分支系統的核心哲學: | 狀況 | 用語感解釋 | |-----------------------------|----------------------------------------| | `branch` 是什麼? | 就是「從現在這一版,分出一條平行宇宙」 | | `checkout` 是什麼? | 是「跳去另一個宇宙繼續寫」 | | `merge` 是什麼? | 是「把你支線劇情拍好的內容剪進主線」 | | `rebase` 又是什麼? | 是「我把支線劇情重新剪成一條主線影片(時光倒流合併)」| --- ### 📦 基本分支指令語法 × 操作說明 | 操作目標 | Git 指令 | 語感翻譯 | |------------------------|------------------------------------------|----------------------------------------| | 查看有哪些分支 | `git branch` | 我有哪些平行宇宙? | | 建立新分支 | `git branch <分支名>` | 開一條新劇情線(但還沒切過去) | | 建立並切過去 | `git checkout -b <分支名>` | 一鍵:開分支+馬上跳過去 | | 切換分支 | `git checkout <分支名>` | 現在開始走這個宇宙 | | 新版切換語法(推薦) | `git switch <分支名>` / `-c` 建新分支 | 更直覺的切換指令 | | 合併分支(進主線) | `git merge <分支名>` | 把子劇情剪進主線(會產生 merge commit) | | 刪除分支 | `git branch -d <分支名>` | 用完這個支線了,可以收掉 | #### 📘 實際範例: ``` # 查看目前在哪個分支 git branch # 新建一條 feature 分支 git checkout -b feature/login-page # 編輯完畢 → 切回主線 git checkout main # 合併分支進來 git merge feature/login-page ``` #### 📎 補充比較:merge vs rebase | 行為 | 說明 | 版本歷史長相 | 何時用? | | -------- | ----------------- | ----------------- | ------------ | | `merge` | 合併兩條分支,保留交叉紀錄 | 有一條分叉線,commit 有交錯 | 團隊多人開發時建議用 | | `rebase` | 把我的 commit 排進別人底下 | 看起來像直線,沒有分支痕跡 | 自己整理分支歷史時可以用 | #### 🧠 總結語感: 分支就是「讓你同時擁有多個版本世界」,每條都是獨立的故事線。 合併就像「剪輯成一條劇情線」,Git 幫你控制衝突、合併紀錄、時間軸。 --- ### 🌐 遠端同步 × Git × GitHub 怎麼搭配 🎯 當你想要 ——「把本機的版本推上去給別人看,或把別人的更新拉下來」 這時候,你就正式進入了「本機 Git ↔ 遠端 Git」的同步領域。 #### 📦 Git 遠端系統的基本概念 | 名稱 | 說明 | 語感翻譯 | |--------------|-----------------------------------|------------------------------| | remote | 遠端倉庫的別名(預設叫 origin) | GitHub 是我給這份專案的雲端儲存地點 | | push | 把本機的 commit 推到遠端 | 上傳你的版本 | | pull | 把遠端的版本拉下來,並試圖合併 | 下載並合併別人的更新 | | fetch | 把遠端版本拉下來但不合併 | 先看看別人做了什麼,不急著合併 | | clone | 從遠端整包複製下來 | 把 GitHub 專案整套搬進本機 | #### 📘 最常用的流程:第一次連上 GitHub ``` # 第一次要連上 GitHub(或其他 Git 遠端) git remote add origin https://github.com/你的帳號/倉庫.git # 設定 main 為上傳的目標分支(只需設定一次) git branch -M main # 把你的版本上傳給遠端 git push -u origin main ``` ##### 📎 語感翻譯: > `remote`:給我一個暱稱叫 origin,指向 GitHub 上的倉庫 > `push`:我把本機這條時間線推上去 > `-u` 是幫你「建立本機與遠端的配對關係」,以後只打 git push 就好 #### 🧪 常用的遠端同步指令清單 | 操作目標 | Git 指令 | 語感翻譯 | | ---------- | ---------------------------- | ---------------------- | | 查看遠端設定 | `git remote -v` | 看看我綁了哪些 GitHub 倉庫 | | 建立遠端連結 | `git remote add origin <網址>` | 幫這個專案指定遠端儲存位置 | | 把版本推上去 | `git push` | 上傳我剛剛的 commit | | 把別人的版本拉下來 | `git pull` | 把 GitHub 上的新內容拉下來+合併進來 | | 只拉但不合併 | `git fetch` | 先抓資料回來,但等等再說要不要合併 | | 拉回整個專案(初次) | `git clone <網址>` | 把別人的整包 project 搬來我本機 | ##### 📎 pull ≠ fetch | 指令 | 會發生什麼事? | 適合情境 | | ------- | --------------- | ------------- | | `pull` | 拉下來 + 嘗試自動合併 | 平常用,快速同步 | | `fetch` | 只拉資料,暫時不動你的本地版本 | 想看差異、手動控制合併時用 | #### 🧯 常見地雷區 | 地雷狀況 | 解法說明 | | ------------------------ | --------------------------------------- | | `push` 時報錯:分支不存在 | 先設定 `git branch -M main` + `-u` 配對 | | 拉別人改動時發生衝突 | 使用 `git pull` → 手動解衝突後 `add` + `commit` | | `push` 說你不是這個 repo 的擁有者 | 確認你的 GitHub 登入帳號& HTTPS / SSH 權限 | | 同一專案重複 init + clone 混在一起 | 建議直接刪掉整包、用 `clone` 重來(別混用!) | --- #### 🧠 總結語感 1. Git 的「遠端功能」就像讓你和朋友共用一份時光機日誌。 2. push:我寫好了 → 傳上雲端 3. pull:別人寫了新內容 → 我同步一下 4. clone:我拿到完整的專案複本,含所有歷史 --- ### 🛠️ 錯誤修復與還原 × 搶救 Git 現場 🎯 當你遇到 ——「改錯了、交錯了、想回去、但不要全炸掉!」 這章節就是: > Git 的「Ctrl + Z」系統,但多了歷史、精度、選擇權、版本回溯。 #### 📦 常見錯誤修復情境 × 功能地圖 | 想做的事 | 對應 Git 指令 | 語感說明 | |----------------------------------|----------------------------------|--------------------------------------| | 退回暫存區(取消 git add) | `git reset <檔名>` | 把剛剛打勾的取消,退回工作區 | | 退回上一次 commit(還沒 push) | `git reset --soft HEAD~1` | 回到上一版,但保留檔案內容與暫存區 | | 退回上一次 commit 且清空暫存區 | `git reset --mixed HEAD~1` | 回到上一版,讓你自己重新挑選要提交的檔案 | | 整個回復到上一個 commit 狀態 | `git reset --hard HEAD~1` | 全清:檔案內容、暫存都退回 | | 單檔案回復(還原檔案內容) | `git checkout <檔名>` | 回復該檔案到最近一次 commit 狀態 | | 還原某個 commit(保留歷史) | `git revert <commit 編號>` | 製造一個「反向改動」的 commit | | 突然想回到很久以前某一版 | `git log` → `git checkout <hash>` | 回到那個 commit 的狀態瀏覽 | | 搞砸了想找回一切(看你曾經去過哪) | `git reflog` → `reset` | Git 的時光足跡日誌,找回任何你曾經 checkout 過的 HEAD | #### 📘 重點語感說明: 🔧 reset vs revert? | 指令 | 操作本質 | 使用時機 | |-----------|----------------------------------|------------------------------------| | `reset` | 回到某個 commit(會改歷史) | 開發中、還沒 push、想要真的「收回來」 | | `revert` | 產生一個「反向 commit」保留歷史 | 已經 push,不能動歷史時使用,像是「補救紀錄」 | ✅ `reset`:像是回到前一天重寫日記,**你把那頁撕掉** ✅ `revert`:像是寫了一頁「道歉信」貼在日記上,**改錯,但留紀錄** #### 📘 stash 是什麼? 🪄 `git stash`:暫時把目前修改收起來 適合:你改到一半,突然要切分支或去做別的事,但又不想 commit | 操作 | 語感翻譯 | |--------------------|-------------------------------| | `git stash` | 把目前改動收進抽屜,清空桌面 | | `git stash list` | 查看抽屜裡有哪些草稿 | | `git stash pop` | 把抽屜最上面的草稿拿出來用 | | `git stash apply` | 拿指定草稿編號出來套用 | | `git stash drop` | 把某份草稿丟掉 | #### 🧯 Git 修復大法總結表(濃縮對照版) | 問題類型 | 指令 | 備註 | |--------------------|-------------------------------------|--------------------------| | commit 消失 | `git reflog` + `reset` | 能找回幾乎所有 HEAD 變動 | | 還沒 commit 就改爛 | `git checkout <file>` | 回到上一次 commit 狀態 | | add 錯檔案了 | `git reset <file>` | 還沒 commit 可以退 | | commit 太早交了 | `git commit --amend` | 改訊息 or 補進新檔案都可以 | | pull 有衝突 | 手動解衝突 + `add` + `commit` | 保持冷靜慢慢處理 | #### 🧠 總結語感: > Git 是「可逆開發系統」,不是只會一條路走到黑。 > 它給你很多「後悔的機會」,但也要求你知道你想退回什麼、為什麼退。 ### 🧹 歷史整理 / 美化 × 乾淨版本管理職人技巧 🎯 當你想要 ——「整理 commit 紀錄、修改訊息、合併多個 commit」 這一章適合你在「功能寫完了」之後,回頭清理歷史、讓版本紀錄好讀、易查、能交差。 #### 📘 為什麼要整理歷史? | 沒整理過的 Git log | 整理過的 Git log | |----------------------------------|------------------------------------| | fix bug again | feat: 調整 login 頁面流程 | | add something | fix: 修正 token 失效邏輯 | | oops | refactor: 優化 API 處理邏輯 | 整理 commit 不只是美觀,而是「讓自己與團隊更清楚每個改動的意圖與脈絡」。 #### 📦 常見整理技巧 × 功能說明 | 功能目標 | Git 指令 | 語感翻譯 | |--------------------|--------------------------------------|--------------------------------------| | 修改上一次 commit 訊息 | `git commit --amend` | 改一張剛剛送出去的便條紙 | | 補進新檔案到上一個 commit | `git add <file>` → `--amend` | 再加菜送進剛剛那份便當 | | 合併多個 commit | `git rebase -i HEAD~3` | 進入編輯模式,把三個 commit 揉成一個 | | 合併時不要開新紀錄 | `git merge --squash` | 把分支的改動壓成一份,主線只記一次 | | 對某個版本打 tag | `git tag v1.0` / `git tag -a` | 幫某版掛名牌,像是「這是正式版 v1.0」 | | 刪除 tag | `git tag -d v1.0` | 拔掉那張名牌 | | 傳 tag 上去 | `git push origin <tag>` | 把名牌一起交出去 | #### 🧪 rebase -i 是什麼? 是進入「編輯 commit 歷史」的互動模式。 ``` git rebase -i HEAD~3 ``` 會出現類似這樣的畫面: ``` pick 7a1f3a1 fix: 修錯字 pick 9c8f2b3 fix: 再修一次 pick b1f9a82 fix: 修好了 # 你可以把其中幾個改成 squash(壓進上一個) ``` ##### 📎 語感翻譯: > `pick` = 保留 > `squash` = 壓進上一個 > `reword` = 改 commit 訊息 --- #### 📘 tag 是什麼? Tag 就像是幫某次 commit 掛一個版本號/說明。 你可以在 git log 裡快速看到哪一版是 v1.0、v2.1、beta-4: ``` git tag v1.0 git tag -a v2.0 -m "正式發佈" git push origin v2.0 ``` ##### 🔖 通常用於: > 正式發佈版本(release) > 部署記錄 > 分辨測試階段版本 #### 🧯 小提醒: | 地雷狀況 | 建議用法 | | ----------------- | ----------------------------- | | `rebase` 用錯導致版本衝突 | 小步進行,先 `rebase -i HEAD~2` 嘗試 | | 不小心把 commit 壓錯 | 可用 `reflog` 回到 rebase 前的 HEAD | | 忘記 push tag 上去 | `git push origin --tags` | ##### 🧠 總結語感: Git 不只是要記錄「你做過什麼」, 更重要的是讓「讀你歷史的人知道你為什麼做」。 > `amend` = 修補剛剛的記錄 > `rebase` -i = 整理歷史成一條清晰直線 > `tag` = 幫某次關鍵 commit 掛上名字與意義 ## 五、 Git 急救包 × 面對爆炸狀況要怎麼救? 👇「當你不小心亂改、亂交、衝突爆炸、檔案消失……該怎麼救回來?」 1. pull 衝突現場處理術 2. commit 消失找回法(reflog 急救) 3. add 錯檔案的撤退術 ### 🧯 實戰地雷 01:pull 發生衝突,整包畫面炸掉 #### 🚨 情境: 你在 pull 別人的改動時,畫面跳出紅字錯誤: CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result. 你:🫠「什麼?!發生了什麼事?」 #### 😵 狀況說明: 你改了一些檔案,別人也改了一樣的檔案, 而且改的地方「重疊」了 → Git 不知道要保留哪個版本。 這時候 Git 就不幫你自動合併了,需要你「手動處理衝突」。 #### 🛠️ 解法流程: 1️⃣ 先看有哪些檔案出現衝突: ``` git status ``` 2️⃣ 打開檔案,會看到長這樣的標記: ``` <<<<<<< HEAD (你這邊的內容) ======= (別人的內容) >>>>>>> origin/main ``` 3️⃣ 手動選擇要保留誰的內容,也可以合併兩邊  然後刪掉上面那幾行分隔符號。 4️⃣ 解完衝突後,要把檔案加入暫存區: ``` git add index.html ``` 5️⃣ 最後提交一個解衝突的 commit: ``` git commit -m "解決 pull 衝突" ``` #### ✅ 總結語感: pull 衝突 ≠ 失敗,代表 Git 讓你當「裁判」 這是一個三步驟機制: 1. 發現衝突(Git 幫你標記) 2. 人腦決定(你手動處理) 3. 結束合併(add → commit) 🌟 請記住: 衝突是「 Git 尊重你選擇的權利 」,不是 bug,是 feature! ### 🧯 實戰地雷 02:commit 消失了!?怎麼找回? #### 🚨 情境: 你用了某種 reset 或 rebase,回頭一看…… 😱「剛剛的 commit 怎麼不見了啦!!」 明明剛才還在 `git log` 裡看得到,現在整條歷史都消失了。 你打算放棄人生。 #### 😵 狀況說明: 你可能做了這些操作之一: - git reset --hard - git rebase 搞錯 HEAD - git checkout 搞錯 commit 這些操作都可能「改變 HEAD 指向」或「砍掉某段歷史」 而 `git log` 是看不到那些已經被斷開連結的 commit。 BUT!Git 其實還記得你去過哪裡。 #### 🛠️ 解法流程(Git 的時光隧道:reflog) 1️⃣ 使用這條指令開啟 Git 的足跡追蹤器: ``` git reflog ``` 你會看到像這樣的紀錄: ``` 47c6f6d HEAD@{0}: reset: moving to HEAD~1 f3a2b8c HEAD@{1}: commit: 調整首頁版面 bb937de HEAD@{2}: commit: 新增 login 元件 ``` > 每一行都是你曾經去過的 HEAD 位置(包含你 reset 前的狀態) 2️⃣ 找到你想要回去的那個 commit(例:f3a2b8c) 3️⃣ 用這條指令回去那一版(軟性還原): ``` git reset --soft f3a2b8c ``` > ✅ 這會把 HEAD 拉回去,但保留你的檔案改動與暫存區內容 (如果你確定要整個檔案也回去,請加 --hard) #### 總結語感: > Git 是失憶症但有備份的版本控制系統 - `git log`:只能看到「還連著 HEAD」的歷史 - `git reflog`:可以看到「你曾經去過哪裡」 - `git reset <reflog 編號>`:就像時光倒轉回那一刻 🌟 一個 reset 不小心砍掉東西不用慌,reflog 是你的救命快照機! ### 🧯 實戰地雷 03:不小心 add 錯了檔案 #### 🚨 情境: 你正準備 commit,打完 `git add .` 後突然驚覺: 「等等,我不想把 config.json 一起交出去啊啊啊啊啊!!」 打 `git status` 一看,它已經變綠色了(代表進暫存區了) 你心跳加速、手汗狂冒,想撤退卻不知道該怎麼辦。 #### 😵 狀況說明: 你用了 `git add` 把某些檔案加入了「暫存區」, 也就是已經被 Git 認定「你準備要交出去的東西」。 但這時候你還沒 `commit`,所以……還來得及救! #### 🛠️ 解法流程: 👉 使用這條指令,**把暫存區的檔案退回工作區** ``` git reset <檔名> ``` 📦 範例: ``` git reset config.json ``` 這樣做的結果是: 1. config.json 還會留在工作區(你的改動不會不見!) 2. 它只是退出了清單,不會被 commit 出去了 3. git status 看起來會從綠色 → 紅色(表示:修改過但沒 add) ✅ 如果你要退掉所有檔案的 add: ``` git reset ``` ✅ 總結語感: > Git add 就像打勾要交出去,reset 是取消勾選。 你只要還沒 commit,add 都是可以退回的。 你沒有真的交出去,還有選擇權! 🌟 reset 是 Git 裡的「退件」機制,不是刪除,是取消暫存。 ## 六、 Git 指令大全 × 功能對照 × 語感翻譯 ### 🔹 專案初始化 #### 🔸 git init  🔧 功能:初始化 Git,讓這個資料夾進入版本控制模式  📐 語法結構:git init  💡 搭配使用:可接 .gitignore、一開始建專案必備  ❗ 常見錯誤:重複在已 clone 專案中再 init(會衝突) #### 🔸 git clone 【網址】  🔧 功能:複製整個 Git 專案下來(含紀錄)  📐 語法結構:git clone <遠端倉庫網址>  💡 搭配使用:初次加入團隊 / 複製模板專案  ❗ 常見錯誤:clone 下來後還再 init(會導致衝突) #### 🔸 .gitignore  🔧 功能:設定不要被 Git 追蹤的檔案清單  📐 語法結構:每一行一個項目,如:node_modules/  💡 搭配使用:init 之後立即建立 .gitignore  ❗ 常見錯誤:已經被 add 的檔案不會自動忽略 --- ### 🔹 版本控制 #### 🔸 git status  🔧 功能:查看目前工作區和暫存區的狀態差異  📐 語法結構:git status  💡 搭配使用:add 前 / pull 後 / merge 時建議多看  ❗ 常見錯誤:沒看 status 就直接 commit(可能漏掉東西) #### 🔸 git add 【檔名】  🔧 功能:把變更加入準備提交的清單(暫存區)  📐 語法結構:git add <檔名> / . / *.js  💡 搭配使用:add → commit 是一組行動  ❗ 常見錯誤:只打 git add(沒加內容 → 無效) #### 🔸 git commit -m "【訊息】"  🔧 功能:提交目前暫存區內容,寫入歷史紀錄  📐 語法結構:git commit -m "文字說明"  💡 搭配使用:add → commit  ❗ 常見錯誤:忘記 add → 沒內容被提交 #### 🔸 git log  🔧 功能:查看歷史 commit 紀錄  📐 語法結構:git log / git log --oneline  💡 搭配使用:revert / tag / reset 前必看  ❗ 常見錯誤:看錯 HEAD 或找不到想回去的 commit --- ### 🔹 分支管理 #### 🔸 git branch  🔧 功能:列出所有分支,顯示目前在哪  📐 語法結構:git branch  💡 搭配使用:checkout 前可用來確認位置  ❗ 常見錯誤:忘記自己在哪個分支操作 #### 🔸 git checkout 【分支】  🔧 功能:切換分支  📐 語法結構:git checkout <分支名>  💡 搭配使用:與 -b 建立分支合用  ❗ 常見錯誤:未 commit 時切換會出現警告 #### 🔸 git checkout -b 【分支名】  🔧 功能:建立並立即切換到新分支  📐 語法結構:git checkout -b feature/login  💡 搭配使用:開始新功能開發時使用  ❗ 常見錯誤:重名分支會報錯 #### 🔸 git merge 【分支名】  🔧 功能:把指定分支內容合併進目前分支  📐 語法結構:git merge dev  💡 搭配使用:回到 main → 合併 feature  ❗ 常見錯誤:衝突需手動處理(conflict) #### 🔸 git rebase 【分支名】  🔧 功能:把當前分支重疊接到別人分支之後  📐 語法結構:git rebase main  💡 搭配使用:想要一條乾淨的 commit 歷史  ❗ 常見錯誤:多人協作不要用 rebase 修改公開歷史 --- ### 🔹 遠端同步 #### 🔸 git remote -v  🔧 功能:列出目前綁定的遠端倉庫  📐 語法結構:git remote -v  💡 搭配使用:檢查是否有綁定 origin / upstream  ❗ 常見錯誤:未綁定遠端卻嘗試 push #### 🔸 git push  🔧 功能:把 commit 推上 GitHub  📐 語法結構:git push / git push origin main  💡 搭配使用:首次建議加 -u 設定預設上傳分支  ❗ 常見錯誤:本地與遠端分支名稱不同 #### 🔸 git pull  🔧 功能:拉取遠端更新並合併  📐 語法結構:git pull  💡 搭配使用:開工前、merge 前建議先 pull  ❗ 常見錯誤:pull 導致 conflict(需解衝突) #### 🔸 git fetch  🔧 功能:拉更新但不自動合併  📐 語法結構:git fetch  💡 搭配使用:想先觀察遠端變動再決定是否合併  ❗ 常見錯誤:fetch 完忘記合併會沒感覺 --- ### 🔹 修復與還原 #### 🔸 git reset 【檔名】  🔧 功能:取消暫存,把檔案退回工作區  📐 語法結構:git reset config.json  💡 搭配使用:add 錯檔案時立刻救援  ❗ 常見錯誤:以為 reset = 檔案刪除,其實不是 #### 🔸 git reset --soft HEAD~1  🔧 功能:回到上一個 commit,保留暫存與檔案  📐 語法結構:git reset --soft HEAD~1  💡 搭配使用:誤 commit 想再改內容時  ❗ 常見錯誤:推上去後不建議 reset(會改歷史) #### 🔸 git checkout 【檔名】  🔧 功能:還原單一檔案為最近 commit 狀態  📐 語法結構:git checkout style.css  💡 搭配使用:某檔案改爛了想回復  ❗ 常見錯誤:會覆蓋檔案內容,不能復原 #### 🔸 git revert 【commit】  🔧 功能:產生一個「反向操作」的 commit  📐 語法結構:git revert f6e2a3  💡 搭配使用:公開歷史不能動時的回滾方法  ❗ 常見錯誤:不是「刪掉」,而是新增一個「反方向改動」 #### 🔸 git stash  🔧 功能:把目前的修改暫存起來  📐 語法結構:git stash / git stash pop  💡 搭配使用:改到一半突然要切分支  ❗ 常見錯誤:忘記 pop 回來,以為東西不見 #### 🔸 git reflog  🔧 功能:查看 HEAD 所有歷史移動紀錄  📐 語法結構:git reflog  💡 搭配使用:reset 出錯、commit 消失時超重要  ❗ 常見錯誤:明明可以救回來卻不知道 reflog 存在 --- ### 🔹 歷史整理與標記 #### 🔸 git commit --amend  🔧 功能:修改上一個 commit(訊息 / 補檔案)  📐 語法結構:git commit --amend  💡 搭配使用:剛剛忘記加某檔案或訊息打錯  ❗ 常見錯誤:已經 push 再 amend 會改歷史,需 force 推送 #### 🔸 git rebase -i HEAD~3  🔧 功能:進入互動式歷史修改(合併 / 改訊息)  📐 語法結構:git rebase -i HEAD~n  💡 搭配使用:交作業 / 公開專案前整理歷史  ❗ 常見錯誤:操作錯誤會衝突,需配合 reflog 使用 #### 🔸 git tag v1.0  🔧 功能:幫某次 commit 掛版本號  📐 語法結構:git tag v1.0 / git tag -a  💡 搭配使用:發佈版本、部署、記錄關鍵版本  ❗ 常見錯誤:忘記 `git push origin v1.0` → 標籤沒上去 ## 七、 總結 × Git 大師之路 ### 🧠 Git 的思維是什麼?本質像什麼系統? #### 🔸 Git 就像是一個「時間導向的版本記錄員」。 它不只是幫你備份檔案,而是幫你記下:  誰在什麼時間點,對哪個檔案,做了什麼改動,為什麼要改。 ##### 🔸 本質上,它比較像: ✅ 一套「決策歷程管理系統」 ✅ 一個可以記錄、分歧、回朔、合併的時間導演 ✅ 一個自動生成「版本歷史書」的工具 >🔹 比起 Google 雲端同步、備份硬碟,Git 更在乎的是:  ➡️ 決策的過程 × 結果的可追蹤性 × 團隊之間的合併邏輯 --- ### ‼️ 一般使用情境 × Git 日常操作流程包(含變動欄位提示)✨ #### 🪄 我現在要「上傳新的專案」到 GitHub(第一次上傳) ##### 📌 步驟: 1. 進入專案資料夾 2. 初始化 Git 3. 建立 README 檔 4. 加入所有檔案 5. 提交 commit 6. 設定預設分支名稱為 main 7. 綁定遠端 GitHub 倉庫 8. 推送上去! ##### 👇 實際操作: ``` cd 【專案資料夾路徑】 git init echo "# 【專案名稱】" >> README.md git add . git commit -m "【你的 commit 訊息】" git branch -M main git remote add origin https://github.com/【你的帳號】/【你的倉庫名】.git git push -u origin main ``` ##### 📌 commit 編輯器建議寫法(會打開文字編輯器): 新增登入功能與首頁樣式 - 加入 Login.vue 元件,完成表單驗證與 API 串接 - 新增首頁版面與 Banner 區塊 - 建立 README.md 檔案 🔧 補充技巧: 若不想用 Vim,而想用 VSCode 編輯 commit 訊息: ``` git config --global core.editor "code --wait" ``` ↓ ``` cd 【專案資料夾路徑】 git init echo "# 【專案名稱】" >> README.md git add . git config --global core.editor "code --wait" git branch -M main git remote add origin https://github.com/【你的帳號】/【你的倉庫名】.git git push -u origin main ``` --- #### 🪄 我現在要「更新之前的專案」 ##### 📌 步驟: 1. 進入專案資料夾 2. 查看改動 3. 加入所有改動 4. 提交 commit 5. 推送遠端 ##### 👇 實際操作: ``` cd 【專案資料夾路徑】 git status git add . git config --global core.editor "code --wait" git push ``` ##### 📌 commit 編輯器建議寫法: 修正購物車與頁面錯誤 - 修正商品刪除後總金額未更新的問題 - 解決手機版無法點擊「加入購物車」的 bug - 更新 cart.vue 與 productList.vue --- #### 🪄 保留本地檔案,但不要它出現在 GitHub 上(移除追蹤) ##### 📌 步驟: 1. 將該檔案移出 Git 追蹤(保留本地) 2. 加入 .gitignore 3. commit 這次變更 4. 推送上去 ##### 👇 實際操作: ``` git rm --cached 【檔案名稱】 echo 【檔案名稱】 >> .gitignore git add .gitignore git commit -m "移除【檔案名稱】並忽略未來版本控制" git push ``` ##### 📌 說明: `.gitignore` 是告訴 Git:「這些東西之後都不要再記錄」。 適合放敏感資料、node_modules、個人設定檔等。 --- #### 🪄 我只要「上傳一個檔案」到 GitHub(不是整個資料夾) ##### 📌 步驟: 1. 進入該檔案所在資料夾 2. 初始化 Git 3. 只加入該檔案(不要用 `.`) 4. 提交 commit 5. 命名分支為 main 6. 綁定 GitHub 倉庫 7. 第一次推送上去 ##### 👇 實際操作: ``` cd 【資料夾路徑】 git init git add 【檔案名稱】 git config --global core.editor "code --wait" git branch -M main git remote add origin https://github.com/【你的帳號】/【你的倉庫名】.git git push -u origin main ``` --- ### 🚨 實戰中要注意哪些地方? | 開發階段 | 常見注意事項 | |--------------------|------------------------------------------------------------| | 初始化階段 | `.gitignore` 要及早設定,避免不必要的檔案進入版本控制 | | 日常開發 | `add` 和 `commit` 不要亂用 → 只記錄真正重要的歷史點 | | 分支操作 | 要先確認當前分支,分支命名要清楚,切分支前記得 commit/stash | | 合併階段 | `pull` 前先 `status`,合併完後記得 `commit`,衝突時不要慌張 | | 錯誤處理與還原階段 | 熟悉 `reset`, `reflog`, `revert`, `stash` → 出錯也不怕 | | 提交遠端階段 | push 前確認 remote 配對、分支一致性,避免強制覆蓋 | | 發佈與交接階段 | 使用 `tag` 做標記,`rebase -i` 清理 commit,留下乾淨歷史 | --- ### 🧰 各階段需要掌握的重點技能是什麼? | 等級 | 能力標準 | 必會工具 / 思維方式 | |----------|------------------------------------------|----------------------------------------------------------| | 🐣 初學者 | 了解基本流程,能進行簡單版本提交 | `init`, `add`, `commit`, `status`, `log` | | 🛠 實務者 | 熟悉分支與合併,能參與多人專案 | `branch`, `checkout`, `merge`, `pull`, `push` | | 🧯 急救者 | 懂得怎麼補救錯誤操作,能幫助別人處理混亂現場 | `reset`, `reflog`, `revert`, `stash`, `checkout` | | 🧼 清潔者 | 會整理歷史紀錄、補充錯誤訊息,讓版本清楚好讀 | `commit --amend`, `rebase -i`, `squash`, `tag` | | 🧬 系統者 | 能架構大型專案流程、模組化、建立 hook 自動化機制 | `submodule`, `hook`, `format-patch`, `cherry-pick` | --- ### 最後總結 ✨Git不可怕,可怕的是你不知道現在你要幹嘛✨