Article Outline
Git 協作筆記
流程指令:
- 從 main 分出一個 README branch:
git checkout main
git pull origin main
git checkout -b README
- 編輯 README.md 並提交:
# 編輯 README.md
vim README.md
git add README.md
git commit -m "Edit README.md for documentation updates"
- 從 main 更新到最新版本並進行 rebase:
git checkout main
git pull origin main
git checkout README
git rebase main
- 處理可能的衝突(如有發生):
- 若 rebase 過程中發生衝突,Git 會提示需要手動解決衝突:
vim 《衝突的檔案》
git add 《衝突解決後的檔案》
git rebase --continue
- 將更新後的分支推送到遠端:
git push origin README
- 發起合併請求並完成合併(例如透過 GitHub/GitLab)。
- 合併後刪除分支(可選):
git checkout main
git pull origin main
git branch -d README
git push origin --delete README
這樣做的好處
- 保持歷史乾淨:
- 使用 rebase 將最新的 main 歷史應用到 README 分支,避免產生多餘的合併記錄(merge commit),讓歷史更加直觀。
- 降低衝突風險:
- 在合併前進行 rebase,提早解決可能的衝突,確保與最新的 main 一致,減少合併時的困擾。
- 提高協作效率:
- 在推送分支前先整合最新的 main 變更,確保其他人也能更快獲得整合後的結果,減少額外溝通成本。
- 便於追蹤問題:
- 每次變更都經過單獨的 commit 和 rebase,可以精確地追蹤哪一次修改導致問題,方便日後維護。
- Git 提交歷史清晰:
- 避免產生無意義的 merge commit,讓專案的歷史更加簡潔易讀。
rebase 和 merge 的差異說明
基本概念
- rebase(變基)
- 將你的分支變更「重新套用」在另一分支的最新提交上,像是把歷史「搬到」最新的基準點。
- 提交歷史會被「重寫」成線性,像是你的分支從未脫離過主分支。
- merge(合併)
- 將兩個分支的歷史合併在一起,會產生一個新的「合併提交」(merge commit)。
- 提交歷史保持完整,保留所有分支的分岔記錄。
工作流程比較
- 使用 rebase 的情境:
- 當你想讓提交歷史保持乾淨且線性。
- 當你正在開發功能,並希望你的分支與主分支保持一致。
- 在提交尚未推送到遠端時,進行本地 rebase。
範例
假設主分支 main 提交如下:
A - B - C (main)
你的功能分支 feature 提交如下:
A - B - X - Y (feature)
當執行 git rebase main,feature 的歷史會變成:
A - B - C - X' - Y' (feature)
- 使用 merge 的情境:1. 當你想保留提交歷史的真實分支結構,便於追蹤所有變更的來源。2. 當你希望整合多個分支的工作,而不重寫提交歷史。3. 在多人協作中,使用 merge 可避免混亂的歷史重寫。 範例: 假設主分支 main 提交如下:
A - B - C (main)
你的功能分支 feature 提交如下:
A - B - X - Y (feature)
當執行 git merge main 後,會生成:
A - B - C - X - Y - M (feature)
\____/
merge commit
優缺點比較
特性 | rebase | merge |
---|---|---|
提交歷史 | 線性歷史,乾淨,容易閱讀 | 保留完整歷史,包含分支的所有分岔 |
衝突處理 | 每次提交都需要解決一次衝突 | 一次性處理所有衝突 |
適用情境 | 個人開發、準備清理提交歷史 | 團隊協作,保留真實的開發歷史 |
是否會重寫歷史 | 會,舊的提交被重新生成 | 不會,提交歷史完全保留 |
是否生成合併提交 | 不會 | 會 |
注意事項
- rebase 的潛在風險:
- 因為它會「重寫歷史」,如果你已將原分支推送到遠端並進行了 rebase,可能會導致其他開發者的分支出現衝突。
- 在多人協作中,避免對公共分支(如 main)使用 rebase。
- merge 的潛在缺點:
- 提交歷史會變得冗長,尤其是在小型功能開發中,容易產生過多的合併提交。
總結
- 用 rebase:當需要乾淨的線性歷史,且適用於個人開發或提交未推送遠端時。
- 用 merge:當需要保留完整歷史,且適用於多人協作和公開分支時。
當兩人開發時,選擇 rebase 或 merge 的策略應根據協作的需求與團隊規範來決定。以下是兩人開發的情境及建議流程
情境 1:兩人需要密切同步
- 適合使用 rebase,讓提交歷史保持線性,便於雙方追蹤最新的修改。
操作流程
- A 開發者的步驟:
- 從 main 分出 feature-A 分支,進行開發並提交更改:
git checkout main
git checkout -b feature-A
# 編輯並提交
git add .
git commit -m "Add feature A"
- 將分支推送到遠端供 B 同步:
git push origin feature-A
- B 開發者的步驟:
- 同步最新的分支並開始開發:
git fetch origin
git checkout -b feature-B origin/feature-A
- 提交更改並推送:
# 編輯並提交
git add .
git commit -m "Add feature B"
git push origin feature-B
- 雙方同步最新的更改(使用 rebase):
- A 拉取 B 的修改並 rebase:
git fetch origin
git rebase origin/feature-B
- 解決衝突後繼續:
vim <conflicting_file>
git add <conflicting_file>
git rebase --continue
4. 完成後合併到 main:
- A 或 B 將最新的分支整合回 main:
git checkout main
git pull origin main
git merge feature-A
git push origin main
好處
- 乾淨的線性歷史便於理解與追蹤。
- 適合雙方變更密集,頻繁需要同步的情境。
情境 2:兩人各自開發,最後整合
- 適合使用 merge,保留兩人各自的提交歷史,讓分支結構更明確。
操作流程
- A 和 B 各自從 main 分支開發:
- A 分支:
git checkout main
git checkout -b feature-A
# 提交更改
git add .
git commit -m "Add feature A"
git push origin feature-A
- B 分支:
git checkout main
git checkout -b feature-B
# 提交更改
git add .
git commit -m "Add feature B"
git push origin feature-B
2. A 或 B 將兩人工作合併到 main:
- 切換到 main 並更新:
git checkout main
git pull origin main
- 合併 A 和 B 的分支:
git merge feature-A
git merge feature-B
- 解決衝突(如有):
vim <conflicting_file>
git add <conflicting_file>
git commit
3. 推送到遠端:
git push origin main
好處
- 提交歷史保留每個人的貢獻,對於大範圍功能開發非常清晰。
- 不需要重寫歷史,適合對歷史敏感的團隊。
比較:rebase vs merge 在兩人開發的適用情境
特性 | rebase | merge |
---|---|---|
歷史清晰度 | 線性歷史,乾淨整齊 | 保留所有分支結構,顯示貢獻來源 |
協作同步 | 適合需要頻繁同步修改的情境 | 適合獨立開發後最終整合的情境 |
衝突處理頻率 | 每次 rebase 需要處理衝突 | 一次性處理所有衝突 |
重寫歷史風險 | 是,有重寫歷史風險,需避免對公共分支使用 | 否,歷史完整保留 |
適用場景 | 小型開發、雙方緊密合作、歷史需保持乾淨 | 大範圍功能開發、需完整記錄所有分支的貢獻 |
結論
- 若兩人密切合作,建議使用 rebase,可保持歷史清晰,但需注意避免影響公共分支。
- 若兩人獨立開發,最後整合,建議使用 merge,方便保留所有分支的完整歷史。