iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
Vibe Coding

《我與 AI 的奇幻漂流:30 天,把「能跑」變成「能上線」》系列 第 13 篇

【Day 13|繫上繩子】分支、PR 與合併:讓 AI 大改之前,先留一條退路

  • 分享至 

  • xImage
  •  

這幾天改了很多地方:資料模型、路徑、參數、搜尋框的字級… 目前都是全部都改在預設的 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 為什麼特別?

其實 main 本身沒有什麼特殊能力。它只是現在大部分新專案預設的主要分支名稱(有些比較舊的專案叫 master),技術上你也可以把它改成別的名字。

它之所以特別,是因為一般會 約定 它是正式的版本。

之後把網站部署上線時,我們可以把 main 設成正式站使用的分支。這樣一來,只有合進 main 的東西,才會出現在使用者面前。

我們還沒部署,但這個習慣值得從現在開始養成:main 放確定可以用/使用者會看得到的版本;還在試的東西,放在別的分支。


三、需要幾條分支?

這件事沒有標準答案,每個人、每個團隊的習慣都不一樣。

對現在這個一個人開發的專案,我選擇先用最簡單的一套:

main    ●───────●─────────────────────●───────
                │                     ↑
                │     開分支 → 改 → 合併回來 → 刪掉
                │                     │
feature         └───●───────●─────────┘
  • main:目前確認可以用的版本
  • 要做一個功能、或讓 AI 大改:從 main 開一條新分支
  • 做完了:合併回 main,然後把這條分支刪掉

這種做完就合併、很快就刪掉的分支,可以把它想成一條工作分支。

有些團隊還會另外維護長期的開發分支或測試分支。我在其他專案也會這樣做,因為我使用的部署平台會自動部署 main,所以如果我一直在 main 分支開發的話,我改了什麼,使用者都會即時看到。不過現在在文章中,可以先用最簡單的「main 加工作分支」就好。

而對 Vibe Coding 來說,短分支特別有價值。AI 改東西很快,一次可能動到十幾個檔案。改得越快、改得越多,越需要一個可以整條丟掉的地方。 AI 可以放心試,main 不用跟著一起冒險。


四、開分支與切換

4.1 你現在站在哪一條線上?

有了分支之後,第一件要知道的事是:我現在在哪一條上?

在 Cursor 裡,將左側面板切換成版本控制面板後,左下角就會顯示目前的分支名稱。點一下右鍵,可以開新分支(Create new branch),也有很多其他的操作,例如以 Github 開啟,或是說可以查看程式碼更動的地方...等等。

https://ithelp.ithome.com.tw/upload/images/20260927/20178017YEvQ3t3o5q.png
【圖 1|Cursor 版本控制面板】 (左下角藍色圓圈的是本機commit位置;紫色的雲朵是最新的遠端分支位置)

分支名稱有很多種合法的寫法。我自己的習慣是跟 Day 9 定 slug 時差不多:小寫英文、用連字號分隔,而且看名字就知道在做什麼。例如 mobile-fix、redesign-card。

4.2 切換分支,檔案會跟著變

這是第一次用分支時最容易嚇一跳的地方。

假設你在 new-design 這條分支上改了幾個檔案、也 commit 了。這時候切回 main——編輯器裡的檔案內容會直接變回去,剛剛的改動全部不見了。

再切回 new-design,改動又全部回來。

切到 main        →  資料夾裡是「存檔3」的樣子
切到 new-design  →  資料夾裡是「存檔5」的樣子

改動沒有消失,它們只是存在另一條線上。你站到哪一條,資料夾裡的檔案就會變成那一條的樣子。

4.3 切換之前,先 commit

有一個要注意的事情:還沒 commit 的改動,只是放在資料夾裡,還沒被存進任何一個存檔點。

切換分支的時候,這些改動有時會跟著你一起跑到另一條分支上;如果會跟另一條分支的內容衝突,Git 有可能直接不讓你切。

最簡單的習慣是:要切分支之前,先把手上的改動 commit。 還沒改完也沒關係,存一個「進行中」的存檔點就好;或者等改到一個段落再切。


五、PR:合併之前,先看一次

分支上的東西改好了,接下來要把它合併回 main。

main          ●───────●───────────────────●
                      │                   ↑
new-design            └───●───────●───────┘
                                    合併

合併可以直接在電腦上做,但我比較建議先把分支推上 GitHub,開一個 PR(Pull Request)。

PR 就是一份「我想把這條分支合進 main」的申請。

你可能會想:我一個人開發,申請給誰看?給你自己看。 PR 最有用的地方,是它會把這條分支改了哪些檔案、每個檔案改了哪幾行,整份列在同一頁。

平常讓 AI 改東西,它會在對話裡告訴你「我改了這幾個地方」。但那只是它的摘要。

對話裡的「我改了 6 個地方」是 AI 的說法;PR 裡列出來的改動,才是實際發生的事。

包括那些它順手改了、卻沒跟你說的地方,在 PR 裡都藏不住。

PR 也可以交給另一個 AI 看

PR 也是讓另一個 AI 幫忙檢查的好時機。有兩件事要注意:

  • 不要只說「幫我 review」。 沒有方向的話,它常常只會挑命名和格式。給它清單會好很多,例如「檢查有沒有動到桌機版的樣式」「檢查有沒有刪掉原本的功能」
  • 它是第二雙眼睛,不是你的替身。 審查的 AI 也可能指出不存在的問題、漏掉真正的問題。自己跑一次網站、看過改動、做完驗收,這些還是你的事

合併之後

在 GitHub 上合併完,還有兩件小事:

  • 把 GitHub 上的更新拉回電腦:合併發生在 GitHub 上,你電腦裡的 main 還不知道。Day 5 用 git push 把東西推上去,這裡要用 git pull 反過來,把 GitHub 上的最新內容拉下來,並合併到你目前這條分支
  • 把用完的分支刪掉:它的任務已經完成了

六、改壞了怎麼辦?

分支最大的價值,其實在這一節。

還沒合併:整條丟掉

main          ●───────●───────────────●
                      │
new-design            └───●───────✕     ← 整條刪掉

切回 main,把那條分支刪掉就好。main 從頭到尾都沒被碰過。

這裡有一個細節:用指令刪分支時,Git 會擋下「還沒合併過」的分支,避免你誤刪。如果你確定就是要丟掉,要用強制刪除(git branch -D,大寫的 D)。大寫的意思是「我知道它還沒合併,照樣刪」,所以用之前要確定。

已經合併了:用 Revert 撤回

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。


七、讓 AI 操作 Git

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 在不同分支上做出完全不同的設計風格,再把它們放在一起比較——不只是說「這個比較好看」,而是說得出 好在哪裡 。最後選一條合併,其他的丟掉。

這會是第一次,真的把分支當成實驗空間,而不只是備份。繩子繫好了,明天放小艇出去探路。

我們明天見。


上一篇
【Day 12|下水試航】響應式設計與 ngrok 實機測試:開發者工具看不見的事
下一篇
【Day 14|三艘小艇】同一份 Skill、三個 AI,會走出三種什麼設計?
系列文
《我與 AI 的奇幻漂流:30 天,把「能跑」變成「能上線」》 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言