# 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/)