這幾天改了很多地方:資料模型、路徑、參數、搜尋框的字級… 目前都是全部都改在預設的 main 分支上。
這種情況可能會出現一個問題:如果其中一個改動把桌機版弄壞了,而我已經接著改了下一個,要怎麼只退掉壞的那一個?
或是另一種情況:明天我想讓 AI 試幾種完全不同的設計風格,看看哪一種比較好。如果全部都在 main 上試,試完三種,如果試完一個要是另外一種,要接著直接改?還是會到之前的存檔再改?
今天我們將更深入探討 git 的機制,先不動程式碼,而是把觀念畫清楚:在讓 AI 大改之前,要怎麼先繫上一條更安全繩子。 明天再實際走一次。
Day 5 說過,Git 就像遊戲的存檔機制:每一次 commit,就是一個存檔點。但到目前為止,我們的存檔點都排在同一條線上:
main ●───────●───────●───────●───────●───────●
存檔1 存檔2 存檔3 存檔4 存檔5 存檔6
└── 開始試新設計 ──┘
假設從存檔 3 之後開始試新設計,試到存檔 6 才覺得不好。這時候想退回去,就得先分清楚:4 ~ 6裡面,哪些是新設計、哪些是順手修的 bug?所有東西混在同一條線上,想只拿掉其中一部分,就會變得很麻煩。
玩遊戲的時候遇到這種情況,我們會怎麼做?
另開一個存檔欄位。
從目前的進度開一個新欄位去冒險。打贏了很好;打輸了,原本的存檔還在,什麼都沒損失。這個「另開的存檔欄位」,在 Git 裡叫做分支(branch)。
main ●───────●───────●───────────────●
│
new-design └───●───────●
存檔4 存檔5
新設計的存檔都留在新設計的分支上,main 的內容不會跟著往前走。
這裡先把分支想成另一個存檔欄位就好。實際上 Git 不會真的把整份專案複製一遍,所以開一條分支幾乎是瞬間的事。
所以如果要用一句話分清楚 Day 5 和今天:
commit 解決的是「我要回到哪個時間點」(留下一個新的時間點);branch 解決的是「我想先走另一條路,但不影響現在這條」。
其實 main 本身沒有什麼特殊能力。它只是現在大部分新專案預設的主要分支名稱(有些比較舊的專案叫 master),技術上你也可以把它改成別的名字。
它之所以特別,是因為一般會 約定 它是正式的版本。
之後把網站部署上線時,我們可以把 main 設成正式站使用的分支。這樣一來,只有合進 main 的東西,才會出現在使用者面前。
我們還沒部署,但這個習慣值得從現在開始養成:main 放確定可以用/使用者會看得到的版本;還在試的東西,放在別的分支。
這件事沒有標準答案,每個人、每個團隊的習慣都不一樣。
對現在這個一個人開發的專案,我選擇先用最簡單的一套:
main ●───────●─────────────────────●───────
│ ↑
│ 開分支 → 改 → 合併回來 → 刪掉
│ │
feature └───●───────●─────────┘
這種做完就合併、很快就刪掉的分支,可以把它想成一條工作分支。
有些團隊還會另外維護長期的開發分支或測試分支。我在其他專案也會這樣做,因為我使用的部署平台會自動部署 main,所以如果我一直在 main 分支開發的話,我改了什麼,使用者都會即時看到。不過現在在文章中,可以先用最簡單的「main 加工作分支」就好。
而對 Vibe Coding 來說,短分支特別有價值。AI 改東西很快,一次可能動到十幾個檔案。改得越快、改得越多,越需要一個可以整條丟掉的地方。 AI 可以放心試,main 不用跟著一起冒險。
有了分支之後,第一件要知道的事是:我現在在哪一條上?
在 Cursor 裡,將左側面板切換成版本控制面板後,左下角就會顯示目前的分支名稱。點一下右鍵,可以開新分支(Create new branch),也有很多其他的操作,例如以 Github 開啟,或是說可以查看程式碼更動的地方...等等。

【圖 1|Cursor 版本控制面板】 (左下角藍色圓圈的是本機commit位置;紫色的雲朵是最新的遠端分支位置)
分支名稱有很多種合法的寫法。我自己的習慣是跟 Day 9 定 slug 時差不多:小寫英文、用連字號分隔,而且看名字就知道在做什麼。例如
mobile-fix、redesign-card。
這是第一次用分支時最容易嚇一跳的地方。
假設你在 new-design 這條分支上改了幾個檔案、也 commit 了。這時候切回 main——編輯器裡的檔案內容會直接變回去,剛剛的改動全部不見了。
再切回 new-design,改動又全部回來。
切到 main → 資料夾裡是「存檔3」的樣子
切到 new-design → 資料夾裡是「存檔5」的樣子
改動沒有消失,它們只是存在另一條線上。你站到哪一條,資料夾裡的檔案就會變成那一條的樣子。
有一個要注意的事情:還沒 commit 的改動,只是放在資料夾裡,還沒被存進任何一個存檔點。
切換分支的時候,這些改動有時會跟著你一起跑到另一條分支上;如果會跟另一條分支的內容衝突,Git 有可能直接不讓你切。
最簡單的習慣是:要切分支之前,先把手上的改動 commit。 還沒改完也沒關係,存一個「進行中」的存檔點就好;或者等改到一個段落再切。
分支上的東西改好了,接下來要把它合併回 main。
main ●───────●───────────────────●
│ ↑
new-design └───●───────●───────┘
合併
合併可以直接在電腦上做,但我比較建議先把分支推上 GitHub,開一個 PR(Pull Request)。
PR 就是一份「我想把這條分支合進 main」的申請。
你可能會想:我一個人開發,申請給誰看?給你自己看。 PR 最有用的地方,是它會把這條分支改了哪些檔案、每個檔案改了哪幾行,整份列在同一頁。
平常讓 AI 改東西,它會在對話裡告訴你「我改了這幾個地方」。但那只是它的摘要。
對話裡的「我改了 6 個地方」是 AI 的說法;PR 裡列出來的改動,才是實際發生的事。
包括那些它順手改了、卻沒跟你說的地方,在 PR 裡都藏不住。
PR 也是讓另一個 AI 幫忙檢查的好時機。有兩件事要注意:
在 GitHub 上合併完,還有兩件小事:
git push 把東西推上去,這裡要用 git pull 反過來,把 GitHub 上的最新內容拉下來,並合併到你目前這條分支分支最大的價值,其實在這一節。
main ●───────●───────────────●
│
new-design └───●───────✕ ← 整條刪掉
切回 main,把那條分支刪掉就好。main 從頭到尾都沒被碰過。
這裡有一個細節:用指令刪分支時,Git 會擋下「還沒合併過」的分支,避免你誤刪。如果你確定就是要丟掉,要用強制刪除(git branch -D,大寫的 D)。大寫的意思是「我知道它還沒合併,照樣刪」,所以用之前要確定。
main ●───────●───────●───────────●
↑ ↑
合併進來 Revert
(新增功能) (把那次改動反過來做一遍)
已經合進 main 的東西,可以用 Revert 撤回。GitHub 在已合併的 PR 頁面上通常會提供 Revert 按鈕,也可以用指令做。Revert 不會刪掉任何紀錄,而是再新增一個存檔點,內容剛好是把那次改動反過來。「合併過」和「撤回過」兩件事都留在歷史裡,之後還查得到。
這跟下一節會提到的 reset 剛好相反:
Reset 比較像把這條線退回以前的位置;Revert 則是在原本歷史後面,再補上一筆「把那次改動取消」的紀錄。
我自己出門用筆電、回家用桌機。有好幾次,在桌機上改完推上 GitHub,出門後忘了先 pull,就直接在筆電上接著改。
這時候,兩邊的 main 都是從同一個存檔點往後走,但各自多了不同的存檔:
GitHub 的 main ●───────●───────● 桌機的存檔
│
筆電的 main └───────● 筆電的存檔
在筆電上 push 時,Git 會拒絕,因為 GitHub 上有筆電還沒有的東西。Cursor 通常會提示你同步:先把 GitHub 上的新內容整合進來,再推上去。
分支名稱從頭到尾都是 main,但在 Cursor 的版本控制圖上,歷史看起來就像分成兩條線、又合起來。
對 Git 來說,筆電上的你和桌機上的你,就像兩個人在開發。
如果兩邊改到同一段,而且 Git 沒辦法自己判斷該怎麼合,就會停下來請你選。這叫做衝突。
真正遇到的時候再處理,會比現在背解法有用。但有一個小習慣可以少遇到很多次:每次坐下來開始工作,先 pull。 Cursor 左下角的同步按鈕按一下就好。如果手上還有上次沒存的改動,先 commit 再 pull。
Day 5 建議過:剛開始接觸 Git 的話,先自己做幾次。
等你自己開過分支、合併過之後,就可以把一部分交給 AI。Codex CLI 本身就能下 Git 指令。
但要分清楚誰負責什麼:
| 誰 | 做什麼 |
|---|---|
| 你決定 | 什麼時候開分支、要不要合併、要不要丟掉 |
| AI 可以幫忙 | 在分支上 commit、寫 commit 訊息、推上 GitHub、開 PR |
| 要你明確同意 | 會改寫或丟掉紀錄的操作 |
最後一項值得說清楚。Git 有幾個指令威力很大:
git reset --hard:可能丟掉還沒存的改動,或把目前的分支退回較早的存檔點git push --force:可能改寫 GitHub 上的紀錄這些指令本身不是錯的,有時候確實需要。問題在於,如果你沒有先限制,AI 遇到 Git 卡住時,可能會選擇比較激進的做法來快速解決,而你可能根本沒注意到。
明天實際操作時會用到,先列在這裡。Cursor 左下角的分支選單和左側的版本控制面板,也都做得到同樣的事。
| 想做什麼 | 指令 |
|---|---|
| 看有哪些分支、自己在哪一條 | git branch |
| 開一條新分支並切過去 | git switch -c 分支名稱 |
| 切換到已經存在的分支 | git switch 分支名稱 |
| 第一次把新分支推上 GitHub | git push -u origin 分支名稱 |
| 開 PR(Day 5 裝過 GitHub CLI) | gh pr create |
| 把 GitHub 上的更新拉回來 | git pull |
| 刪掉已經合併的分支 | git branch -d 分支名稱 |
| 強制刪掉還沒合併的分支 | git branch -D 分支名稱 |
-D只在「確定要放棄這條分支」時才用,不要把它當成一般的刪除指令。
今天沒有實際操作,換成幾個情境,檢查一下觀念:
| 情境 | 該怎麼做 |
|---|---|
| 想讓 AI 重新設計卡片,但不確定會不會比較好 | 從 main 開一條新分支,在分支上改 |
| AI 說改好了,想確認它到底動了什麼 | 開 PR,看列出來的改動 |
| 分支上的新設計試完,覺得不好 | 切回 main,把分支刪掉 |
| 新功能已經合進 main 了,才發現有問題 | 用 Revert 撤回那次合併 |
| 在 GitHub 上合併完,電腦裡的 main 還是舊的 | 切到 main,git pull |
| 改到一半想切到別的分支 | 能 commit 就先 commit,或等改到一個段落再切 |
| 換了一台電腦要繼續開發 | 先 pull,再開始改 |
| AI 說「我用 force push 把問題解決了」 | 停下來確認紀錄有沒有被改寫,並在 prompt 裡要求它之後先問你 |
如果你曾經在電腦裡看過這種檔名:
報告.docx
報告_v2.docx
報告_v2_修改.docx
報告_final.docx
報告_final_真的final.docx
那你其實已經在做一件很像分支的事了。
想試一個新寫法,又怕改壞原本的,所以另存一份;試完覺得不錯,再把內容複製回去。分支做的是同一件事,只是 Git 會幫你記住每一份從哪裡分出來、改了什麼、什麼時候合回去。
而在團隊裡,PR 還多了一層意義:它是同事之間互相審查 的地方。我改的東西,先讓你看過、留言、確認沒問題,才合進大家共用的 main。
前面說過,兩台電腦的你就像兩個人。多人開發時,這件事每天都在發生:你在分支上做了三天,main 可能已經被同事合進好幾個改動。所以很多團隊會盡量讓工作分支不要拖太久,因為拖得越久,跟 main 的差異通常越大,合併時越容易麻煩。
今天沒有寫任何一行程式,只做了一件事:把「要讓 AI 大改之前,先開一條分支」這個觀念畫清楚。 改成功了,合併回來;改壞了,整條丟掉。不管哪一種,main 都還在原地。
明天要實際走一次,讓 AI 在不同分支上做出完全不同的設計風格,再把它們放在一起比較——不只是說「這個比較好看」,而是說得出 好在哪裡 。最後選一條合併,其他的丟掉。
這會是第一次,真的把分支當成實驗空間,而不只是備份。繩子繫好了,明天放小艇出去探路。
我們明天見。