# 🧙♀️\ 我要成為 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不可怕,可怕的是你不知道現在你要幹嘛✨