All Articles

2024-11-21

Git 協作筆記

流程指令:

  1. 從 main 分出一個 README branch:
git checkout main
git pull origin main
git checkout -b README
  1. 編輯 README.md 並提交:
# 編輯 README.md
vim README.md
git add README.md
git commit -m "Edit README.md for documentation updates"
  1. 從 main 更新到最新版本並進行 rebase:
git checkout main
git pull origin main
git checkout README
git rebase main
  1. 處理可能的衝突(如有發生):
  2. 若 rebase 過程中發生衝突,Git 會提示需要手動解決衝突:
vim 《衝突的檔案》
git add 《衝突解決後的檔案》
git rebase --continue
  1. 將更新後的分支推送到遠端:
git push origin README
  1. 發起合併請求並完成合併(例如透過 GitHub/GitLab)。
  2. 合併後刪除分支(可選):
git checkout main
git pull origin main
git branch -d README
git push origin --delete README

這樣做的好處

  1. 保持歷史乾淨:

    • 使用 rebase 將最新的 main 歷史應用到 README 分支,避免產生多餘的合併記錄(merge commit),讓歷史更加直觀。
  2. 降低衝突風險:

    • 在合併前進行 rebase,提早解決可能的衝突,確保與最新的 main 一致,減少合併時的困擾。
  3. 提高協作效率:

    • 在推送分支前先整合最新的 main 變更,確保其他人也能更快獲得整合後的結果,減少額外溝通成本。
  4. 便於追蹤問題:

    • 每次變更都經過單獨的 commit 和 rebase,可以精確地追蹤哪一次修改導致問題,方便日後維護。
  5. Git 提交歷史清晰:

    • 避免產生無意義的 merge commit,讓專案的歷史更加簡潔易讀。

rebase 和 merge 的差異說明

基本概念

  • rebase(變基)
  • 將你的分支變更「重新套用」在另一分支的最新提交上,像是把歷史「搬到」最新的基準點。
  • 提交歷史會被「重寫」成線性,像是你的分支從未脫離過主分支。
  • merge(合併)
  • 將兩個分支的歷史合併在一起,會產生一個新的「合併提交」(merge commit)。
  • 提交歷史保持完整,保留所有分支的分岔記錄。

工作流程比較

  • 使用 rebase 的情境:

    1. 當你想讓提交歷史保持乾淨且線性。
    2. 當你正在開發功能,並希望你的分支與主分支保持一致。
    3. 在提交尚未推送到遠端時,進行本地 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,讓提交歷史保持線性,便於雙方追蹤最新的修改。

操作流程

  1. A 開發者的步驟:
  2. 從 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
  1. B 開發者的步驟:
  2. 同步最新的分支並開始開發:
git fetch origin
git checkout -b feature-B origin/feature-A
  • 提交更改並推送:
# 編輯並提交
git add .
git commit -m "Add feature B"
git push origin feature-B
  1. 雙方同步最新的更改(使用 rebase):
  2. 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,保留兩人各自的提交歷史,讓分支結構更明確。

操作流程

  1. A 和 B 各自從 main 分支開發:
  2. 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,方便保留所有分支的完整歷史。