Git Cherry-Pick:如何選擇並應用特定的提交

在協作軟體開發環境中使用分支是必不可少的,可以隔離功能、錯誤修復或實驗。然而,有時您需要從一個分支中提取特定變更並應用到另一個分支,而不是合併整個分支。這就是git cherry-pick派上用場的地方。

本教程的目標是提供如何有效使用git cherry-pick的全面指南。您將學習這個命令的語法,了解如何處理衝突,並探索最佳實踐和要避免的常見問題。讓我們開始吧!

什麼是Git Cherry-Pick?

git cherry-pick命令是一個基本的Git命令,可以讓開發人員對其原始碼具有精細控制。

與其他Git操作不同,例如合併(merge)或變基(rebase)會處理整個分支,櫻桃挑選(cherry-pick)允許您從一個分支中選擇特定提交並應用到另一個分支。這提供了精確性,特別是在您只需要整合特定更改而不是分支中的所有修改時。

git cherry-pick命令通過複製所選提交的內容並在目標分支中創建新的提交來工作,保持提交歷史的完整性。

何時使用git cherry-pick

git cherry-pick的使用案例包括:

  • 回溯錯誤修復:您已經在開發分支中解決了一個錯誤,需要在穩定或發布分支中應用相同的修復。挑選可以讓您移動錯誤修復,而不會攜帶其他不相關的更改。
  • 應用緊急修補:當生產環境需要一個關鍵修復,而開發分支繼續發展時,挑選使您能夠提取並應用修復到生產分支。
  • 功能隔離進行測試:在測試期間可能只需要測試與某一功能相關的特定提交。與合併整個功能分支不同,挑選所需的提交可以保持測試分支的整潔和高效。
  • 更正錯誤提交:如果一個提交錯誤地推送到了錯誤的分支,您可以使用 cherry-pick 將提交應用到適當的分支,而不會干擾項目歷史。
  • 在多個分支之間重複使用更改:在需要在多個分支之間應用相同更新的情況下,cherry-pick 允許您在不重新進行工作或引入分支複雜性的情況下在不同分支中複製更改。

Git Cherry-Pick 的語法

了解 git cherry-pick 的語法是有效使用此命令的關鍵。這不僅僅是選擇提交,而是精確應用它們以達到期望的結果。

挑選單一提交的基本語法為:

git cherry-pick <commit-hash>
  • git cherry-pick:啟動該操作的命令。
  • <commit-hash>:您想要挑選的提交的唯一標識符(SHA-1 哈希)。可以通過運行 git log 來列出提交歷史以找到此哈希。

執行上述命令時,Git 將指定提交中的更改應用到當前分支,並創建一個具有相同更改但不同哈希的新提交。

需要注意的是,該命令僅轉移提交本身,而不會轉移原始分支的上下文或父歷史。

剛接觸 Git 和 GitHub?在這個適合初學者的 GitHub 和 Git 教學中開始使用版本控制。

如何使用 Git Cherry-Pick:逐步範例

現在你已經了解 git cherry-pick 的基本語法,是時候看看這個命令如何運作了。

本節提供了實用的範例,帶你走過常見的基本情況和更複雜的情況,這些情況中 cherry-picking 是非常有用的。每個範例都說明了如何將一個或多個提交的更改應用到另一個分支。

範例 1:選擇一個提交

假設你在一個功能分支上進行了修復,想要將其應用到主分支,而不合併整個功能分支。

  • 首先,運行以下命令找到您想要cherry-pick的提交的哈希值:
git log
  • 找到提交的哈希值。
  • 切換到主分支:
git checkout main
  • 運行cherry-pick命令(假設哈希值為abc1234):
git cherry-pick abc1234

當你執行這個命令時,Git 將會將由 abc1234 標識的提交中的更改應用到你的當前分支(在這個例子中是 main)。Git 在主分支上創建一個新的提交,包含與原始提交相同的更改,但具有新的提交哈希。

範例 2:選擇多個提交

在某些情況下,你可能需要將幾個不同的提交從一個分支應用到另一個分支。假設你在功能分支中有三個獨立的提交需要引入到主分支。

  • 使用 git log 查找你想要選擇的每個提交的哈希:
git log
  • 切換到主分支:
git checkout main
  • 運行 cherry-pick 命令,列出提交:
git cherry-pick abc1234 def5678 ghi7890

示例 3: Cherry-picking 一個提交範圍

假設您在功能分支上進行了一系列提交,並希望一次應用它們到主分支而不需要分別指定每個提交。您該怎麼做?

  • 使用 git log 來識別您想 cherry-pick 的開始和結束提交(例如,abc1234ghi7890)。
  • 切換到主分支:
git checkout main
  • 運行帶有提交範圍的 cherry-pick 命令:
git cherry-pick abc1234...ghi7890

示例 4: 從遠端分支 cherry-pick 一個提交

有時候,關鍵的修正存在於遠端分支中,而你希望在不合併整個分支的情況下將其應用到本地分支。以下是如何做到這一點:

  • 從遠端儲存庫獲取最新的變更
git fetch origin
  • 列出遠端分支中的提交,以找到你需要的哈希:
git log origin/feature_branch --oneline
  • 假設你需要的提交哈希是 abc1234
  • 切換到你的本地主分支:
git checkout main
  • 從遠端分支中挑選提交:
git cherry-pick abc1234

這讓您可以應用遠端分支的提交,而不必合併整個分支。

需要檢出遠端分支嗎?請按照這個逐步指南進行 Git 檢出遠端分支

示例 5:挑選一個提交並對其進行修改

如果您挑選了一個提交但需要在提交之前進行輕微修改,您可以使用 Git 的互動模式。以下是方法:

  • 切換到目標分支:
git checkout main
  • 挑選提交但在提交之前停止:
git cherry-pick -n abc1234

這個 -n(或 --no-commit)標誌應用更改但不創建提交。

  • 根據需要修改文件。
  • 手動暫存並提交更改:
git add . git commit -m "Modified cherry-picked commit from feature_branch"

當您需要在最終確定之前調整一個選取的提交時,這非常有用。

處理 Git Cherry-Pick 過程中的衝突

在不同分支之間進行選取提交時,衝突是不可避免的,特別是當代碼庫有顯著分歧時。

雖然cherry-pick旨在乾淨地應用更改,但並非總能自動調和差異。在這些情況下,衝突必須手動解決。了解衝突是如何產生以及如何處理它們對於完成cherry-pick操作至關重要。

衝突是如何發生的

衝突通常發生在從挑選的提交中的更改與目標分支中已存在的更改重疊或矛盾的情況下。例如:

  • 相同行在兩個分支中被修改: 如果代碼的相同行在源分支和目標分支中都被修改,Git 就無法判斷應該應用哪個版本。
  • 在一個分支中刪除但在另一個分支中修改的文件:如果一個文件在一個分支中被刪除,但在挑選的提交中被修改,Git 將不知道是保留它還是應用這些更改。
  • 無關的更改但同一個文件:即使這些更改看似無關,如果它們發生在同一個文件中,Git 可能將其標記為潛在的衝突。

當發生衝突時,Git 將停止 cherry-pick 操作,將您的工作目錄留在一個需要在繼續之前解決的衝突狀態。

解決衝突

一旦發生衝突,Git 將提供衝突檔案的指示,您需要手動解決這些差異。以下是解決衝突的方法:

1. 檢查衝突檔案: 執行以下命令以查看哪些檔案發生衝突:

git status

該命令將顯示包含衝突的檔案列表。

2. 解決衝突: 您可以手動編輯衝突檔案以解決問題。刪除衝突標記(<<<<<<<, =======, >>>>>>>),並決定保留哪些更改或如何合併它們。

3. 使用 Git Mergetool(可选):如果手动解决冲突很麻烦,您可以使用合并工具来帮助可视化和解决冲突:

git mergetool

根据您的配置,上述工具将打开一个可视化合并工具,这样更容易审查和解决冲突。

4. 将冲突标记为已解决:解决冲突后,使用以下命令将文件标记为已解决:

git add <conflicted-file>

5. 完成 cherry-pick:一旦所有衝突都解決並且文件已暫存,執行以下命令完成 cherry-pick:

git cherry-pick --continue

許多現代 IDE 和工具,如 Visual Studio Code 和 GitHub,提供內建的合併衝突解決功能。GitHub 的 Web 介面允許您直接在拉取請求中解決衝突,使得在共享存儲庫上協作而無需切換到本地環境更加容易。

在衝突後跳過提交

有時,解決衝突可能太複雜,或者您可能意識到該提交實際上並不必要。在這種情況下,您可以完全跳過該提交。

1. 中止當前的 cherry-pick 過程: 如果衝突過於複雜,且您不想應用該提交,您可以通過運行以下命令來跳過它:

git cherry-pick --skip

這將放棄衝突的提交並繼續下一個(如果您正在 cherry-pick 多個提交)。

2. 中止整個 cherry-pick: 如果您想完全中止 cherry-pick 操作,您可以運行:

git cherry-pick --abort

這個命令將恢復您的工作目錄到您開始 cherry-pick 之前的狀態。

想要清理你的提交歷史嗎?學習如何將多個提交合併為一個這個Git 壓縮教學

使用 Git Cherry-Pick 的最佳實踐

錯誤地使用 cherry-pick 可能會導致複雜的歷史和項目版本控制中的混淆。為了避免這些陷阱,遵循最佳實踐可以確保你有效地使用 cherry-pick,而不會給代碼庫引入不必要的複雜性。

保持小而具體

挑選提交在用於小而具體的提交時最有效,這些提交解決了明確定義的任務,例如錯誤修復或小功能增強。

避免隨意挑選大型且複雜的提交,這些提交通常會將多個變更捆綁在一起,因為這樣可能會引入衝突並使管理代碼庫變得更加困難。提交越具針對性,應用時就越容易,且不會引發意外的副作用。

記錄你的挑選

為了維持清晰的歷史,始終在挑選時提供適當的上下文。這可以通過詳細的提交信息或文檔中的註釋來實現。

主要的要點是你必須解釋為什麼需要進行挑選。這在跨越長期存在的分支或協作環境時尤其重要,因為這有助於未來的貢獻者理解為什麼變更被選擇性地應用。

檢查提交歷史

在挑选櫻桃之前,請審查源分支和目標分支的提交歷史。這一步幫助確定您即將挑選的提交是否依賴其他更改。缺少依賴關係可能導致功能不完整或錯誤,因此確保挑選櫻桃不會引入半成品功能或更新。

避免過度使用櫻桃挑選

雖然櫻桃挑選便於應用特定更改,但過度使用可能導致分支間重複提交的碎片化歷史。這可能使得追蹤某些更改的來源或理解更廣泛的開發背景變得困難。

在進行櫻桃挑選之前,始終評估合併或變基是更適合的策略。謹慎且有目的地使用cherry-pick以避免混亂提交歷史。

在 Git 中為不必要的檔案而苦惱嗎?學習如何有效使用 .gitignore,請參閱 這個 Git 忽略教學.

解決 Git Cherry-Pick 的常見問題

使用 cherry-pick 時出現的問題需要對 Git 的底層機制有清晰的理解。在本節中,我將介紹一些您在 cherry-picking 時可能遇到的常見問題以及如何解決它們。

挑選不存在的提交

有時,您可能會嘗試挑選一個在當前分支上無法訪問或已經合併的提交。這通常會導致錯誤消息,指出該提交無法找到或應用。

1. 找不到提交记录: 当您尝试挑选的提交哈希在当前存储库或分支上不存在时会出现此问题。请通过在包含提交的分支上使用git log检查提交历史,确保您正在引用正确的提交。解决方法:

  • 仔细检查提交哈希以确保其正确。
  • 验证提交是否存在于您可以访问的分支上。
  • 如果提交在远程分支上,请确保使用git fetch已获取该分支。

2. 已應用的提交: 如果該提交已經合併或櫻桃挑選到目標分支中,Git 將阻止您重複應用它。這一措施有助於保持歷史記錄的清潔,避免多餘的更改。解決方案:

  • 使用 git log 檢查該提交是否已經存在於目標分支中。
  • 如果需要,跳過 cherry-pick 操作,因為更改已經應用過了。

在重新定位或合併後進行櫻桃挑選

在重新定位或合併後進行櫻桃挑選可能會引入複雜性,因為您的分支歷史記錄已被修改。重新定位會重新編寫提交歷史記錄,而合併則會結合分支,這兩者都可能影響櫻桃挑選的適用性。

1. 由於重新定位提交而引起的衝突:重新定位後,提交歷史將被重寫,如果您嘗試挑選在重新定位過程中已被修改的提交,可能會出現問題。當cherry-pick嘗試應用與重寫歷史不一致的更改時,您可能會遇到衝突。解決方法:

  • 使用git log仔細檢查重新定位後的提交歷史,以確保您要挑選的提交尚未被修改。
  • 解決衝突的方法與標準cherry-pick過程相同,使用git status和手動編輯。

2. 合併後的重複提交:合併分支可能導致您想要挑選的提交已經包含在合併歷史中。再次挑選它可能會導致重複提交,這會使您的歷史變得混亂,並且難以追蹤更改。解決方案:

  • 在挑選之前,檢查兩個分支的提交歷史,以確認該提交是否已經被合併。
  • 如果該提交已經在目標分支中,請避免再次挑選相同的提交。

需要在 Git 中撤銷更改嗎?了解在這個 Git 重置和撤銷教程 中何時使用 git resetgit revert

結論

git cherry-pick 是一種強大的方式,可以將特定的提交從一個分支應用到另一個分支,而無需合併整個分支。無論你是要移動一個錯誤修正、一個功能更新,還是僅僅選擇性地應用更改,它都有助於保持你的 Git 歷史乾淨且專注。

在這個指南中,我涵蓋了如何選擇性地挑選單個和多個提交、解決衝突,以及遵循最佳實踐以避免常見的陷阱。通過明智地使用 cherry-pick,你可以改善工作流程,同時保持你的倉庫組織有序。

如果你想加深你的 Git 技能,查看 Git 基礎作為一個強有力的起點。你也可以探索 GitHub 概念介紹,或者通過 GitHub 基礎技能路徑採取結構化的方法。

現在你知道如何像專業人士一樣進行選擇性挑選,快去你的下一個項目中試試吧!

Source:
https://www.datacamp.com/tutorial/git-cherry-pick