---
# System prepended metadata

title: Git 番外篇：進階魔法 - 團隊合作的時間線魔法

---

# Git 番外篇：進階魔法 - 團隊合作的時間線魔法

#### 前篇
[Linux & Git 新手魔法訓練營：從麻瓜到命令列大師](https://hackmd.io/@GDSC-CYCU/Linux-Git-WorkShop)

## 🎓 恭喜你，魔法師！

你已經掌握了 Git 最核心的個人工作流程 (`add` -> `commit` -> `push`)，這相當於學會了如何為自己的魔法筆記建立完美的存檔。

但是，當你需要和其他魔法師一起編寫一部龐大的魔導書時，要如何確保大家不互相干擾，又能將各自完成的章節完美地融合在一起呢？

這份番外篇將教你 Git 中最強大、也最重要的團隊合作魔法：**分支 (Branching)**。

---

## 🚀 分支 (Branch) - 建立屬於你的平行時空

### 為什麼需要分支？

想像一下，主線故事（`main` 分支）正在順利進行。現在，你想嘗試寫一個全新的番外篇（例如開發一個新功能、修復一個 Bug），但你不確定這個嘗試會不會成功，更不希望在嘗試的過程中把主線故事搞得一團亂。

**分支**就是你的解決方案！

它允許你從主線上開闢一個「平行時空」。你在這個平行時空裡做的任何修改，都**不會**影響到主線。直到你確認這個時空裡的內容是完美的，再把它合併回主線。

### 常用指令

| 類別 | 指令 | 說明 |
| :--- | :--- | :--- |
| **查看分支** | **`git branch`** | 列出所有本地端的分支，並用 `*` 標示出你目前所在的分支。 |
| **建立分支** | **`git branch <name>`** | 建立一個新的分支，但**不會**自動切換過去。 |
| **切換分支** | **`git checkout <name>`** | 切換到一個已經存在的分支。就像是跳躍到另一個平行時空。 |
| **建立並切換** | **`git checkout -b <name>`** | ✨ **複合魔法！** 這是最常用的方式，一步完成「建立」和「切換」兩個動作。 |
| **刪除分支** | **`git branch -d <name>`** | 當一個分支的任務完成並合併後，可以用此指令刪除它，保持倉庫整潔。 |

### 🎯 實戰演練

1.  `cd` 進入你上次練習的 `my-first-repo` 資料夾。
2.  輸入 `git branch`，你會看到目前只有一個 `main` 分支。
3.  讓我們來開發一個新功能！輸入 `git checkout -b feature/add-description` 來建立並切換到新分支。
4.  再次輸入 `git branch`，你會看到 `*` 已經移到新分支上了。
5.  使用 `nano hello.txt`，在檔案裡新增一行 "This is a new feature."。
6.  `git add hello.txt`
7.  `git commit -m "Feat: add description"`
8.  現在，這個修改只存在於 `feature/add-description` 這個時空。不信的話，你可以 `git checkout main` 切換回主線，會驚訝地發現 `hello.txt` 裡並沒有你剛新增的那行字！

---

## 🌍 合併 (Merge) - 讓平行時空匯流

當你在分支中的新功能開發完成後，就該是時候讓它回歸主線了。**合併 (Merge)** 就是將一個分支的修改內容，完整地應用到另一個分支上的過程。

### 合併的標準流程

這個流程非常重要，請記住口訣：「**先切換，再合併**」。

1.  **回到你的目標分支**：通常是 `main` 分支。
    ```bash
    git checkout main
    ```
2.  **執行合併指令**：告訴 Git，把 `feature/add-description` 分支的內容合併「進來」。
    ```bash
    git merge feature/add-description
    ```
3.  **清理戰場**：合併成功後，舊的分支通常就沒有用了，可以將它刪除。
    ```bash
    git branch -d feature/add-description
    ```

### ⚠️ 魔法衝突 (Merge Conflict)

有時候，當你和你的夥伴**同時修改了同一個檔案的同一行**時，Git 會陷入困惑。它不知道該保留誰的版本，這時就會發生「**合併衝突**」。

Git 不會擅自作主，而是會把這個難題交給你。它會在衝突的檔案中留下像這樣的特殊標記：

```
<<<<<<< HEAD
這是 main 分支的內容
=======
這是 feature 分支的內容
>>>>>>> feature/add-description
```

你需要做的就是：
1.  手動打開這個檔案。
2.  決定要保留哪個版本（或兩者都保留，或自己重寫）。
3.  **刪除** `<<<<<<<`, `=======`, `>>>>>>>` 這些特殊標記。
4.  儲存檔案後，重新 `git add <檔案名稱>` 和 `git commit` 來告訴 Git：「我已經解決衝突了！」

---

## 🌳 子樹 (Subtree) - 管理外部專案的進階魔法

> 這是更進階的魔法，當你需要將一個完全獨立的 Git 專案，當作你主專案的「一個子資料夾」來管理時，它會非常有用。

### 為什麼需要子樹？

想像一下，你的專案需要用到一個通用的前端 UI 庫，而這個 UI 庫本身也是一個獨立的 Git 專案。你希望將它的程式碼直接放到你的專案中（而不是透過套件管理器），同時又能方便地從原始 UI 庫拉取更新。

`git subtree` 就是為此而生。

### 常用指令

假設你想把 `https://github.com/twbs/bootstrap.git` 這個專案，放到你專案的 `lib/bootstrap` 資料夾下：

1.  **新增子樹**：
    ```bash
    # --prefix 指定要放置的路徑
    git subtree add --prefix=lib/bootstrap https://github.com/twbs/bootstrap.git main --squash
    ```
    `--squash` 會將對方專案的龐大 commit 歷史壓縮成一筆，讓你的主專案保持乾淨。

2.  **更新子樹**：
    當遠端的 `bootstrap` 專案有更新時，你可以用這個指令來拉取最新的程式碼。
    ```bash
    git subtree pull --prefix=lib/bootstrap https://github.com/twbs/bootstrap.git main --squash
    ```

**提醒**：`git subtree` 的概念較為複雜，通常在大型專案或有特殊架構需求時才會使用。初期可以先理解它的應用場景即可。

---

## ✨ 結語

Git 的世界非常廣闊，分支與合併只是團隊協作的起點。當你熟練了這些操作後，你會發現它不僅僅是一個工具，更是一種能讓專案開發流程變得清晰、安全、高效的思維方式。

持續探索，不斷練習，你的魔法將會越來越強大！

---

## 📚 參考資料與延伸閱讀

以下是精選的參考資料，當你遇到特定問題或想深入研究時，它們會是你的好幫手。

### 入門與觀念

*   [簡介 · Git](https://zlargon.gitbooks.io/git-tutorial/content/) - Zlargon 的 Git 圖文教學，非常適合新手。
*   [為你自己學 Git | 高見龍](https://gitbook.tw/) - 台灣最知名的 Git 教學網站之一，內容非常完整。
*   [Git - 與遠端協同工作](https://git-scm.com/book/zh-tw/v2/Git-%E5%9F%BA%E7%A4%8E-%E8%88%87%E9%81%A0%E7%AB%AF%E5%8D%94%E5%90%8C%E5%B7%A5%E4%BD%9C) - 官方文件，說明如何與遠端倉庫互動。
*   [GitHub 入門(二) — 使用終端機上傳檔案到GitHub - 趙子榮 - Medium](https://medium.com/@s110319022/github-%E5%85%A5%E9%96%80-%E4%BA%8C-%E4%BD%BF%E7%94%A8%E7%B5%82%E7%AB%AF%E6%A9%9F%E4%B8%8A%E5%82%B3%E6%AA%94%E6%A1%88%E5%88%B0github-cfa55e1903fa)

### 修改歷史紀錄 (後悔藥系列)

*   [【狀況題】剛才的 Commit 後悔了，想要拆掉重做… - 為你自己學 Git](https://gitbook.tw/chapters/using-git/reset-commit.html)
*   [【狀況題】修改 Commit 紀錄 - 為你自己學 Git](https://gitbook.tw/chapters/using-git/amend-commit1.html)
*   [【狀況題】追加檔案到最近一次的 Commit - 為你自己學 Git](https://gitbook.tw/chapters/using-git/amend-commit2.html)
*   [【狀況題】不小心使用 hard 模式 Reset 了某個 Commit，救得回來嗎？ - 為你自己學 Git](https://gitbook.tw/chapters/using-git/restore-hard-reset-commit)
*   [【Git】修改某次提交的Commit Message_林多-CSDN博客](https://blog.csdn.net/zxc024000/article/details/108939049)
*   [如何修改第一次commit的信息？ - SegmentFault 思否](https://segmentfault.com/q/1010000017932368)

### 分支與合併

*   [合併發生衝突了，怎麼辦？ - 為你自己學 Git](https://gitbook.tw/chapters/branch/fix-conflict.html)
*   [同步遠端分支 · Git](https://zlargon.gitbooks.io/git-tutorial/content/remote/sync.html)
*   [Git操作：從一個分支cherrypick多個commit到其他分支 | 程式前沿](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/681667/)
*   [Git cherry-pick from another repository (Example)](https://coderwall.com/p/sgpksw/git-cherry-pick-from-another-repository)
*   [使用 Git 時如何做出跨 repo 的 cherry-pick | Just for noting](https://blog.m157q.tw/posts/2017/12/30/git-cross-repo-cherry-pick/)
*   [How to update a forked repo with git rebase | by Jill Cates | Medium](https://medium.com/@topspinj/how-to-git-rebase-into-a-forked-repo-c9f05e821c8a)

### 進階主題

*   [Git 進階應用 Submodule 與 Subtree，使用它們來拆分專案 | Puck's Blog](https://blog.puckwang.com/posts/2020/git-submodule-vs-subtree/)
*   [如何打patch 及git 打patch 失败的处理方法_RonnyJiang的博客-CSDN博客](https://blog.csdn.net/RonnyJiang/article/details/54342871)

### 實用技巧

*   [Git Commit Message 這樣寫會更好，替專案引入規範與範例](https://wadehuanglearning.blogspot.com/2019/05/commit-commit-commit-why-what-commit.html)
*   [Git 更換遠端伺服器倉庫網址](https://gist.github.com/fokayx/255b228ded2bca1c4f60)
*   [rename git branch locally and remotely](https://gist.github.com/lttlrck/9628955)
*   [下載Github上特定Repository內的資料夾 - AndyWu's Notes](https://notes.andywu.tw/2018/%E4%B8%8B%E8%BC%89github%E4%B8%8A%E7%89%B9%E5%AE%9Arepository%E5%85%A7%E7%9A%84%E8%B3%87%E6%96%99%E5%A4%BE/)
*   [一些git使用的小技巧 - AKR社区](https://www.akr-developers.com/d/93/2)
*   [如何在區域網路用 Docker 架設有 SSL 的 Gitlab « Nic Lin's Blog](https://blog.niclin.tw/2020/02/10/build-internal-gitlab-by-self-certificate/)
