一文讓你明白 Git 分支是如何工作的
分支是 Git 版本跟蹤的核心功能,并且經(jīng)常被使用相同軟件代碼庫(kù)的團(tuán)隊(duì)使用。我們將深入研究它們?nèi)绾卧谀缓蠊ぷ鳎约叭绾问褂盟鼈儊?lái)改進(jìn) Git 工作流程。
什么是分支?
分支用于拆分 Git 歷史記錄。您可以將 Git 提交想象成一系列可以追溯到過(guò)去的更改。您可以“簽出checkout”任何這些提交,并將本地目錄及時(shí)移回提交時(shí)的狀態(tài)。
分支通常用于處理實(shí)驗(yàn)性功能,或需要一段時(shí)間的更改,或任何其他可能破壞存儲(chǔ)庫(kù)的東西。例如,您可能正在重構(gòu)代碼庫(kù)的一個(gè)重要組件,并且在完成之前,您希望master 分支保持穩(wěn)定。
一旦新feature 分支穩(wěn)定了,它就可以重新合并到master中,通常是通過(guò) 拉取請(qǐng)求,這是一個(gè)允許在進(jìn)行更改之前進(jìn)行代碼審查和測(cè)試的過(guò)程。
然而,在幕后,分支的工作方式與您最初預(yù)期的略有不同。在 Git 中,分支只是指向特定提交的標(biāo)簽或指針。就是這樣,master 分支只是指向最新的提交master;當(dāng)您進(jìn)行新的提交時(shí),標(biāo)簽會(huì)更新為指向新的提交。
雖然將提交視為及時(shí)推進(jìn)是有用的;實(shí)際上,Git 提交指向彼此。每個(gè)提交都有對(duì)最后一次提交的引用,并且這個(gè)鏈用于構(gòu)造存儲(chǔ)庫(kù)的狀態(tài)。
但是,如果您創(chuàng)建一個(gè)新分支,則情況會(huì)有所不同。您簽出的任何分支(使用git checkout <branch>)都將用作新提交的標(biāo)簽。
要在此示例中創(chuàng)建分支,您必須首先確保將存儲(chǔ)庫(kù) HEAD 設(shè)置為master 分支。這是因?yàn)槟鷮?shí)際上可以從任何地方開(kāi)始創(chuàng)建分支——包括過(guò)去的提交或其他分支上的提交。
git checkout master
然后創(chuàng)建一個(gè)新分支,并交換到它:
git branch feature
git checkout feature
此時(shí),您的存儲(chǔ)庫(kù)中的任何內(nèi)容都沒(méi)有改變。feature 和分支標(biāo)簽都master 指向同一個(gè)提交。
但是,您從此時(shí)開(kāi)始提交的任何內(nèi)容都將添加到feature 分支中。更具體地說(shuō),將創(chuàng)建一個(gè)新提交,設(shè)置為指向當(dāng)前提交,并且“功能”標(biāo)簽將更新為指向這個(gè)新提交。
您甚至可以checkout master 在主分支上進(jìn)行更多提交。它不會(huì)影響feature 分支,因?yàn)闃?biāo)簽所知道的只是它指向那個(gè)特定的提交。它不會(huì)隨master 標(biāo)簽更新。
合并和變基(Merging 和 Rebasing)
當(dāng)然,如果分支永遠(yuǎn)卡在那里,它們就不會(huì)太有用了,因此 Git 提供了將它們合并回master 分支的工具。從技術(shù)上講,只要?dú)v史兼容,您就可以將子分支合并到任何其他分支中。
最簡(jiǎn)單的情況是您有一個(gè)只需要合并回來(lái)的簡(jiǎn)單分支。您可以簽出master 分支,然后運(yùn)行g(shù)it merge feature 以將在功能分支上所做的所有提交“重播”到 master 上。
這會(huì)將它們合并到主時(shí)間線中,并使用更改創(chuàng)建一個(gè)新的“合并提交”。
但它并不總是那么簡(jiǎn)單,而且在許多情況下,您將遇到 需要解決的合并沖突。這可能包括分支修改文件中的相同行、文件移動(dòng)或刪除,或feature 在創(chuàng)建分支后更改軟件時(shí)出現(xiàn)的其他類型的錯(cuò)誤。
如果您有一個(gè)長(zhǎng)時(shí)間運(yùn)行的feature 分支,則將這個(gè)問(wèn)題最小化的一種方法是執(zhí)行頻繁的合并,這次相反——從master 主支到 feature 分支上,這保持feature 最新,雖然它并沒(méi)有真正減少所需的工作量,但它可以防止它陷入一片混亂。
這種策略對(duì)于長(zhǎng)期存在的分支很常見(jiàn),通常被認(rèn)為是 Git 的最佳實(shí)踐。
在這種情況下也使用的另一個(gè)工具是變 基?;旧?,變基就像拿起整個(gè)分支并將其移動(dòng)到從新位置開(kāi)始,通常是存儲(chǔ)庫(kù)中的最新提交。在某些情況下,這會(huì)導(dǎo)致更清晰的 Git 歷史記錄,并且是某些復(fù)雜情況的首選解決方案。
然而,Git 歷史是“不可變的”,并且由于這種變基復(fù)制提交而不是實(shí)際移動(dòng)它們。如果沒(méi)有與您的團(tuán)隊(duì)正確協(xié)調(diào),這可能會(huì)導(dǎo)致共享分支上的許多問(wèn)題——如果您重新設(shè)置基準(zhǔn),并且您的同事在“舊”、現(xiàn)已刪除的功能分支上進(jìn)行新提交,它將被擱置。他們將不得不隱藏提交并將其彈出到新分支以協(xié)調(diào)更改。
如何使用分支?
要開(kāi)始創(chuàng)建新分支,您需要將存儲(chǔ)庫(kù)置于正確狀態(tài),以便新分支標(biāo)簽從您想要的位置開(kāi)始。如果您要從 分支master,只需簽出整個(gè)分支以從最新提交開(kāi)始。否則,您可以通過(guò)簽出單個(gè)提交將您的 repo 置于分離的 HEAD 狀態(tài)。
git checkout master
git checkout aa3e570923b8ee61414cec17d9033faab4f084a6
然后,您可以創(chuàng)建新分支,并使用checkout切換到它:
git branch feature
git checkout feature
這可以在一個(gè)命令中完成,帶有-b 結(jié)帳標(biāo)志:
git checkout -b feature
此時(shí),您的 repo 中所做的任何提交都將提交到新分支。
如果您需要再次交換分支,只需運(yùn)行g(shù)it checkout master 即可恢復(fù)正常。
如果您有需要移動(dòng)的本地更改,可以將它們放入git stash. 更改將被存儲(chǔ),并且可以在交換分支后重新應(yīng)用。
git stash
git checkout feature
git stash apply