git提交結(jié)構(gòu)圖
git完整提交結(jié)構(gòu)圖如下所示 full commit graph
圓形代表commit
對(duì)象买喧,橢圓代表分支瑟匆,三角形代表tree
對(duì)象黄娘,長(zhǎng)方形代表blob
對(duì)象
因?yàn)?code>commit對(duì)應(yīng)的tree
和blob
對(duì)象已經(jīng)深入研究過(guò)了骨杂,所以此處使用簡(jiǎn)化圖來(lái)演示分支操作
simplified commit graph(縮減版-圖左)
labeled commit graph(帶標(biāo)簽版-圖右)
git分支操作
分支代表了不同的支線任務(wù)條账嚎,使用分支意味著你可以把你的工作從開(kāi)發(fā)主線上分離開(kāi)來(lái)莫瞬,以免影響開(kāi)發(fā)主線儡蔓,從而并行執(zhí)行不同任務(wù)。
分支是git的核心疼邀,也是git有別于其他版本控制軟件的根本原因喂江,git中鼓勵(lì)多使用分支,對(duì)git而言分支的創(chuàng)建和切換也非常簡(jiǎn)單旁振。
而在很多版本控制系統(tǒng)中获询,分支操作是一個(gè)略微低效的過(guò)程 -- 常常需要完全創(chuàng)建一個(gè)源代碼目錄的副本,對(duì)于大項(xiàng)目而言會(huì)耗費(fèi)很多時(shí)間拐袜。
初始化項(xiàng)目
在demo目錄下初始化git倉(cāng)庫(kù)吉嚣,然后進(jìn)行3次提交操作,每次新增一個(gè)文件進(jìn)行提交阻肿。三次提交的結(jié)構(gòu)圖如下瓦戚,其中master
為缺省(默認(rèn))分支,初始化git倉(cāng)庫(kù)時(shí)即會(huì)創(chuàng)建一個(gè)master
分支丛塌,并且讓HEAD
指向該分支较解。此時(shí)master
分支指向了最新的commit
對(duì)象。
創(chuàng)建分支
創(chuàng)建分支命令:git branch "name"
創(chuàng)建分支的本質(zhì)就是新增一個(gè)指針文件赴邻,指向了當(dāng)前所在分支的commit
對(duì)象印衔,該文件在.git/refs/heads
目錄中,創(chuàng)建一個(gè)分支dev
姥敛,可以看到此時(shí)dev
和master
文件保存了同一個(gè)commit
對(duì)象的hash值
創(chuàng)建分支后的結(jié)構(gòu)圖
切換分支
切換分支命令:git checkout "name"
奸焙,切換分支的本質(zhì)實(shí)際上做了兩步操作
1.改變HEAD
指針的指向,即修改.git/HEAD
文件的內(nèi)容彤敛,指向新分支
2.將新分支對(duì)應(yīng)的commit
對(duì)象所包含的所有內(nèi)容檢出到工作空間
切換分支后結(jié)構(gòu)圖的變化
分叉分支
在dev
分支上修改版本3.txt文件內(nèi)容与帆,然后進(jìn)行提交,切換回master
分支墨榄,修改版本2.txt文件內(nèi)容玄糟,然后進(jìn)行提交。
此時(shí)master
分支和dev
分支就形成了分叉袄秩,分別指向了不同的新的commit
對(duì)象
兩次提交后的結(jié)構(gòu)變化圖如下
合并分支
合并分支命令:git merge "name"
如果我們想將dev分支內(nèi)容合并到master
阵翎,那么首先需要切換到master
分支,然后執(zhí)行git merge
進(jìn)行合并操作之剧,合并后查看版本3.txt和版本2.txt文件內(nèi)容是否都已改變郭卫。
合并分支后會(huì)新生成一個(gè)commit
對(duì)象,該commit
對(duì)象同時(shí)指向了兩個(gè)commit
父對(duì)象背稼,而master
指向了該commit
贰军。注意此時(shí)dev
分支并沒(méi)有移動(dòng),仍然是指向以前的commit
對(duì)象雇庙。
合并分支后的結(jié)構(gòu)圖
fast-forward
fast-forward
-- 特殊的合并谓形,特點(diǎn)是不會(huì)產(chǎn)生新的commit
對(duì)象灶伊,只是改變指針的指向內(nèi)容。
如果創(chuàng)建了一個(gè)分支后寒跳,分支產(chǎn)生了新的提交記錄聘萨,但是master
分支一直沒(méi)有做任何修改操作,此時(shí)如果要合并分支到master
童太,只需要簡(jiǎn)單改變master
的指向?yàn)樽钚碌?code>commit對(duì)象即可米辐。
如圖,我們?cè)?code>master分支指向的commit
對(duì)象上新增加了dev
分支书释,并且在dev
分支上進(jìn)行了一次提交翘贮,此時(shí)合并dev
分支到master
就是fast-forward
合并,只需要將master
指向7a45d對(duì)應(yīng)的commit
對(duì)象即可爆惧。
在我們上面的合并分支示例中狸页,當(dāng)我們切換到dev
分支,然后將master
合并到dev
分支扯再,此時(shí)也是fast-forward
合并芍耘,可以看到dev
分支直接指向了master
指向的commit
對(duì)象,而沒(méi)有產(chǎn)生新的合并commit
對(duì)象。
PS:在產(chǎn)生分叉的分支上進(jìn)行合并時(shí)需要使用一定的算法,而git使用的合并算法為Three-way Merge
卢厂。該算法需要參考兩個(gè)分支共同的commit
對(duì)象,加上分支的兩個(gè)commit
對(duì)象進(jìn)行差異性比較辙谜。
分支總結(jié)
由于 Git
中的分支實(shí)際上僅是一個(gè)包含所指對(duì)象校驗(yàn)和(40 個(gè)字符長(zhǎng)度 SHA-1 字串)的文件,所以創(chuàng)建和銷毀一個(gè)分支就變得非常廉價(jià)和快速了。
這和大多數(shù)版本控制系統(tǒng)形成了鮮明對(duì)比,它們管理分支大多采取備份所有項(xiàng)目文件到特定目錄的方式鳄袍,所以根據(jù)項(xiàng)目文件數(shù)量和大小不同,可能花費(fèi)的時(shí)間也會(huì)有相當(dāng)大的差別吏恭,快則幾秒畦木,慢則數(shù)分鐘。
而 Git
的實(shí)現(xiàn)與項(xiàng)目復(fù)雜度無(wú)關(guān)砸泛,它永遠(yuǎn)可以在幾毫秒的時(shí)間內(nèi)完成分支的創(chuàng)建和切換。同時(shí)蛆封,因?yàn)槊看翁峤粫r(shí)都記錄了祖先信息(譯注:即parent
對(duì)象)唇礁,將來(lái)要合并分支時(shí),尋找恰當(dāng)?shù)暮喜⒒A(chǔ)(譯注:即共同祖先)的工作其實(shí)已經(jīng)自然而然地?cái)[在那里了惨篱,所以實(shí)現(xiàn)起來(lái)非常容易盏筐。 Git
鼓勵(lì)開(kāi)發(fā)者頻繁使用分支,正是因?yàn)橛兄@些特性作保障砸讳。