聊聊Unity项目管理的那些事:Git-flow和Unity
感謝原作者h(yuǎn)ttps://www.cnblogs.com/murongxiaopifu/p/6086849.html
0x00 前言
 目前所在的團(tuán)隊(duì)實(shí)行敏捷開發(fā)已經(jīng)有了一段時(shí)間了。敏捷開發(fā)中重要的一個(gè)話題便是如何對(duì)項(xiàng)目進(jìn)行恰當(dāng)?shù)陌姹竟芾怼m?xiàng)目從最初使用svn到之后的Git One Track策略再到現(xiàn)在的GitFlow策略,中間有經(jīng)驗(yàn)也有教訓(xùn),所以記錄在本文,既是和各位朋友交流也供自己日后查閱。
0x01 基礎(chǔ):Unity項(xiàng)目如何做版本管理?
為什么更喜歡git?
初來項(xiàng)目組到時(shí)候,項(xiàng)目還在使用SVN作為版本管理的工具。作為一個(gè)不喜歡SVN的人,自然而然想到了換用git來做版本管理。這里當(dāng)然并不是說svn不如git好,只是它們的思路的確是不一樣的。
 與SVN相比,git是一個(gè)分布式的版本管理工具。這一點(diǎn)可能是我喜歡git勝過svn的一個(gè)決定性原因。
 當(dāng)我們使用git從遠(yuǎn)端版本庫/服務(wù)器上chect out代碼后,git會(huì)在自己的機(jī)器上克隆一個(gè)自己的本地版本庫。這樣我們?cè)诒镜鼐蛯?shí)現(xiàn)了版本的管理,而不必像svn那樣必須和服務(wù)器連接。舉一個(gè)例子,當(dāng)我們?cè)诒镜亻_發(fā)自己的功能時(shí)一旦不小心有了錯(cuò)誤的操作,我們只需要在本地進(jìn)行版本回退即可。如果使用svn的話,這種問題的修改似乎就變得不那么方便了。
 喜歡git的另一個(gè)原因就是使用git的分支了。我們可以在本地的同一個(gè)工作目錄下快速的切換不同的分支,每個(gè)分支之間都是隔離的。當(dāng)我們不想影響主分支的時(shí)候,可以十分輕松的利用git創(chuàng)建一個(gè)新的分支進(jìn)行開發(fā)。
 總之,使用git替換svn作為團(tuán)隊(duì)的新的版本管理工具之后,團(tuán)隊(duì)的開發(fā)效率提高了很多。
git和Unity
既然項(xiàng)目組決定采用git作為新的版本管理工具,那么首先的一點(diǎn)就是我們要先確認(rèn)哪些文件是需要納入版本管理的。同時(shí),在確認(rèn)需要管理的文件時(shí),順便重新規(guī)整一下整個(gè)項(xiàng)目的目錄結(jié)構(gòu),不僅僅是為了更加便于git進(jìn)行版本管理,同時(shí)也可以更好的維護(hù)項(xiàng)目。
 上圖便是一個(gè)典型的Unity項(xiàng)目的默認(rèn)目錄。我們可以看到默認(rèn)的Unity項(xiàng)目的目錄下就已經(jīng)有很多文件和文件夾了。
 但是,作為版本管理,我們通常只需要關(guān)注兩個(gè)文件夾即可。即:Assets文件夾和ProjectSettings文件夾。
 其中,Assets文件夾主要用來存放項(xiàng)目的資源,例如腳本文件、貼圖、材質(zhì)、聲音資源等等。
 而ProjectSettings文件夾則用來存放一些項(xiàng)目的設(shè)置,例如輸入設(shè)置、物理系統(tǒng)的設(shè)置、Player設(shè)置、Layer、Tags等等。我們可以在Unity的編輯器中的Edit->Project Settings菜單來調(diào)整這些設(shè)置信息。
 默認(rèn)目錄下的其余文件或文件夾都可以由這兩個(gè)文件夾的內(nèi)容生成出來。
 例如,如果Assets文件夾中包括C#腳本文件,則Unity會(huì)在目錄生成C#工程文件Assembly-CSharp.csproj。
 除此之外, Unity的一些特殊的文件夾也會(huì)生成一些工程文件。例如Editor文件夾內(nèi)如果有C#腳本,則會(huì)生成一個(gè)Assembly-CSharp-Editor工程文件。
 除了這些工程文件之外,Unity還會(huì)生成一些文件夾。例如Library、Temp、obj這三個(gè)文件夾。它們同樣是Unity自動(dòng)生成的。
 Library文件夾的內(nèi)容主要是在項(xiàng)目中導(dǎo)入資源時(shí)產(chǎn)生的一些本地的緩存。
 Temp和obj這兩個(gè)文件夾則是在項(xiàng)目構(gòu)建時(shí)產(chǎn)生的臨時(shí)文件。
 因此,我們可以通過git的.gitignore文件來將不需要被git管理的文件/文件夾添加到忽略列表。下面是github提供的一份適用于Unity項(xiàng)目的.gitignore文件列表。
除此之外,我們還需要將Unity為導(dǎo)入資源生成的.meta文件也納入版本管理,和相應(yīng)的資源一同維護(hù)。meta文件的重要性在于Unity會(huì)利用它來處理對(duì)應(yīng)資源之間的引用關(guān)系。
為了處理資源之間的引用關(guān)系,Unity在序列化時(shí)會(huì)通過兩個(gè)數(shù)據(jù)來保證正確的引用關(guān)系。即文件GUID和以及本地ID,其中文件GUID便保存在meta文件中。
fileFormatVersion: 2 guid: 437eb1afce72bb44ca24c6ac3fe90c1d timeCreated: 1453720237 licenseType: Store NativeFormatImporter:userData: assetBundleName: assetBundleVariant:只要使用文本工具打開meta文件即可以看到其內(nèi)容。
另外還需要注意到的事情便是git版本管理時(shí)的文件沖突問題。通常當(dāng)我們合并兩個(gè)相同的地方都有修改的分支時(shí),都會(huì)產(chǎn)生沖突。
一旦git不知道如何自動(dòng)合并,就需要我們來手動(dòng)解決沖突了。如果文件是文本文件,git便會(huì)在有沖突的地方做上標(biāo)記(如 <<<<<<< HEAD ==== >>>>>>> HASH_ID等),參考這些標(biāo)記我們可以很方便的解決沖突問題。
但是,如果文件是二進(jìn)制的文件,一旦發(fā)生沖突則很難查看git插入的沖突標(biāo)識(shí),解決起來是比較棘手的。因此Unity項(xiàng)目的資產(chǎn)序列化最好生成文本文件,而不是二進(jìn)制文件。我們可以在設(shè)置中選擇序列化的策略。
 這樣場景文件和prefab等文件就會(huì)被序列化為yaml文本文件:
智能合并場景和prefab文件
將場景文件和Prefab文件序列化為yaml文本文件之后,仍然有可能會(huì)在合并時(shí)遇到產(chǎn)生沖突的情況。不過好在Unity在5.X版本之后已經(jīng)提供了一個(gè)便于處理合并的工具,并且已經(jīng)集成在Editor中。你可以在你的Unity安裝目錄下的Unity/Editor/Data/Tools文件夾中找到這個(gè)名為YAML Merge的工具。
 它的使用方法也十分簡單,以使用git作為版本管理工具為例。我們需要在.gitconfig文件中加上下面這幾行配置:
這樣當(dāng)兩個(gè)人同時(shí)修改同一個(gè)場景,并且進(jìn)行合并時(shí),之前的git會(huì)報(bào)告這個(gè)沖突,讓我們來手動(dòng)解決該沖突。但是配置了YAML Merge工具之后的git會(huì)調(diào)用YAML Merge工具,并自動(dòng)解決沖突。
 更多相關(guān)的內(nèi)容,各位可以去參考Unity官方的手冊(cè)(https://docs.unity3d.com/Manual/SmartMerge.html)。
0x02 問題:大文件如何處理?
游戲開發(fā),特別是3D游戲開發(fā)時(shí)會(huì)使用到很多美術(shù)資源、音頻視頻資源等等。如何把這些大型的二進(jìn)制文件集成到git工作流中就成為了一個(gè)需要思考的問題。
由于git在處理二進(jìn)制文件時(shí)默認(rèn)會(huì)壓縮并存儲(chǔ)二進(jìn)制文件的所有完整版本,如果二進(jìn)制文件很多,這種做法顯然不是最優(yōu),換句話說git在存儲(chǔ)二進(jìn)制文件時(shí)的效率不高。
針對(duì)這個(gè)問題,github開源了一個(gè)git的拓展,即Git Large File Storage(簡稱LFS),git大文件存儲(chǔ)。規(guī)避了git傳統(tǒng)的處理方法,Git LFS處理大型二進(jìn)制文件的方式是用“文本指針”替換它們。
這些文本指針實(shí)際上是包含二進(jìn)制文件信息的文本文件。文本指針存儲(chǔ)在Git中,而大文件本身通過HTTPS托管在Git LFS服務(wù)器上。Git LFS 使用引用小文本文件指針指向存儲(chǔ)在服務(wù)器的大型文件。
從git lfs的官網(wǎng)下載并安裝好之后,我們就可以在項(xiàng)目中使用lfs來管理我們的大型二進(jìn)制文件了。相關(guān)操作也很簡單:
git lfs track "*.<file_extensions>"例如我們要管理png文件,只需要輸入git lfs track "*.png"就好了。
當(dāng)然,我們也可以直接修改項(xiàng)目目錄下的.gitattributes文件。
*.png filter=lfs diff=lfs merge=lfs -text需要說明的是,很多公司使用的gitlab也已經(jīng)宣布支持Git LFS了。所以項(xiàng)目的管理沒有必要美術(shù)用svn、程序用git了。
0x03 策略:Git One Track 和 GitFlow
使用版本工具,除了要能正確合理的使用它之外,作為項(xiàng)目的管理者,還需要清楚一些和版本管理相關(guān)的策略。
因此,在本文的最后我們?cè)倭牧氖褂胓it作為版本管理工具的管理策略吧。
簡單的說,git的管理策略目前有兩大流派。平時(shí)和同事聊天或和別的公司的朋友交流時(shí)也能夠感覺的到,即Git One Track和Git-flow。
One Track
One Track簡單的說,就是整個(gè)團(tuán)隊(duì)在開發(fā)項(xiàng)目時(shí)都在同一個(gè)分支上進(jìn)行。這也就意味著開發(fā)階段的所有工作都集中在同一個(gè)分支,例如新功能開發(fā)、bug的修復(fù)。當(dāng)然,One Track策略并不意味著只有一個(gè)分支,而是只有一個(gè)開發(fā)分支。當(dāng)達(dá)到團(tuán)隊(duì)設(shè)定的里程碑時(shí),可以開一個(gè)新的分支用來維護(hù)這個(gè)基本穩(wěn)定的版本,這個(gè)維護(hù)分支只進(jìn)行維護(hù)的工作,而不進(jìn)行開發(fā)的工作。同時(shí),開發(fā)分支繼續(xù)進(jìn)行最新的開發(fā)工作。
使用這種策略的最大特點(diǎn)就是大家都在同一個(gè)分支上工作,因此每次提交代碼都有可能會(huì)有沖突。為了減少?zèng)_突,團(tuán)隊(duì)也常常會(huì)提高提交的頻率,同時(shí)每次提交的顆粒度都比較小。同時(shí),管理成本比較低,整個(gè)團(tuán)隊(duì)的學(xué)習(xí)成本也比較低。
在我之前的項(xiàng)目中,參與過一個(gè)剛從svn切換到git的團(tuán)隊(duì),我們使用過一段時(shí)間One Track的工作方式,可以看到這種策略對(duì)整個(gè)團(tuán)隊(duì)接觸和適應(yīng)git還是很有好處的。
但是我相信更多的人還是更推崇另外一種策略,即Git-Flow策略。
GitFlow
首先我相信很多人一定在哪里會(huì)見過下面這張圖:
 這張圖已經(jīng)能很好的說明了gitflow了。即任何變更都是一個(gè)分支。
可以看到,這張圖中的分支雖然很多,但是大體上可以分為兩類。即主要分支和輔助分支。
主要分支
主要分支即git默認(rèn)的mater分支以及一個(gè)主開發(fā)分支develop。
master分支是git默認(rèn)的主分支,平時(shí)團(tuán)隊(duì)不在該分支上進(jìn)行開發(fā)。而主開發(fā)分支develop則管理著開發(fā)人員提交的代碼,當(dāng)代碼穩(wěn)定時(shí)或固定一個(gè)周期,將develop分支上的代碼合并到主分支。
輔助分支
輔助分支是團(tuán)隊(duì)每個(gè)開發(fā)人員都能接觸到的,常見的輔助分支包括:
- 功能分支
- 發(fā)布分支
- 修復(fù)分支
這三類分支都有其對(duì)應(yīng)的使用場景。
開發(fā)新的功能時(shí),需要從主開發(fā)分支上創(chuàng)建一個(gè)新的功能分支,待該分支上的功能開發(fā)完畢之后,再合并會(huì)主功能分支。
發(fā)布分支則是在版本發(fā)布時(shí)創(chuàng)建的分支, 按照產(chǎn)品里程碑的需求包括應(yīng)該完成的功能。
修復(fù)分支則是當(dāng)出現(xiàn)bug時(shí),為了不影響開發(fā)分支,因此創(chuàng)建出一個(gè)新的分支來修改bug,之后再合并回開發(fā)分支。
因此我們可以看到,GitFlow的策略無論是開發(fā)功能還是修復(fù)bug都是以分支的方式來進(jìn)行。這樣做的好處當(dāng)然是管理上十分干凈。但是由于功能開發(fā)時(shí)間相對(duì)要長、代碼提交的粒度相對(duì)較大,因此在分支合并的時(shí)候有可能會(huì)出現(xiàn)沖突的問題,另外一個(gè)問題是對(duì)整個(gè)團(tuán)隊(duì)的要求要比One Track策略大。
不過,并沒有最完美的方案,有的也僅僅是更適合團(tuán)隊(duì)的方案。例如很多團(tuán)隊(duì)包括我現(xiàn)在都更喜歡將兩種方式混合使用,例如針對(duì)One Track都在同一個(gè)分支上開發(fā),可能不夠干凈,我們就可以適當(dāng)?shù)拈_一個(gè)新的分支也用來開發(fā)。針對(duì)GitFlow提交合并時(shí)代碼粒度大、沖突多,我們就每天都同步一次代碼而不必等整個(gè)功能都完成再合并到主開發(fā)分支。
最后也希望大家也一起來聊聊項(xiàng)目管理,特別時(shí)游戲項(xiàng)目管理的一些經(jīng)驗(yàn)吧。
總結(jié)
以上是生活随笔為你收集整理的聊聊Unity项目管理的那些事:Git-flow和Unity的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: [最新原创电子书]lazarus开发者入
- 下一篇: 深度学习—池化、padding的理解
