Вы находитесь на странице: 1из 7

5/8/13 A successful Git branching model nvie.

com

A successful Git branching model


http://nvie.com/posts/a-successful-git-branching-model/
Published:January05,2010

InthispostIpresentthedevelopmentmodelthatIveintroducedforallofmyprojects(bothatworkandprivate)aboutayearago,andwhich
hasturnedouttobeverysuccessful.Ivebeenmeaningtowriteaboutitforawhilenow,butIveneverreallyfoundthetimetodo
sothoroughly,untilnow.Iwonttalkaboutanyoftheprojectsdetails,merelyaboutthebranchingstrategyandreleasemanagement.

ItfocusesaroundGitasthetoolfortheversioningofallofoursourcecode.

Why git?
ForathoroughdiscussionontheprosandconsofGitcomparedtocentralizedsourcecodecontrolsystems,seetheweb.Thereareplentyof
flamewarsgoingonthere.Asadeveloper,IpreferGitaboveallothertoolsaroundtoday.Gitreallychangedthewaydevelopersthinkof
mergingandbranching.FromtheclassicCVS/SubversionworldIcamefrom,merging/branchinghasalwaysbeenconsideredabitscary
(bewareofmergeconflicts,theybiteyou!)andsomethingyouonlydoeveryonceinawhile.

ButwithGit,theseactionsareextremelycheapandsimple,andtheyareconsideredoneofthecorepartsofyourdailyworkflow,really.For
example,inCVS/Subversionbooks,branchingandmergingisfirstdiscussedinthelaterchapters(foradvancedusers),whileineveryGit
book,itsalreadycoveredinchapter3(basics).

Asaconsequenceofitssimplicityandrepetitivenature,branchingandmergingarenolongersomethingtobeafraidof.Versioncontroltools
nvie.com/posts/a-successful-git-branching-model/ 1/7
5/8/13 A successful Git branching model nvie.com

aresupposedtoassistinbranching/mergingmorethananythingelse.

Enoughaboutthetools,letsheadontothedevelopmentmodel.ThemodelthatImgoingtopresenthereisessentiallynomorethanasetof
proceduresthateveryteammemberhastofollowinordertocometoamanagedsoftwaredevelopmentprocess.

Decentralized but centralized


Therepositorysetupthatweuseandthatworkswellwiththisbranchingmodel,isthatwithacentraltruthrepo.Notethatthisrepois
onlyconsideredtobethecentralone(sinceGitisaDVCS,thereisnosuchthingasacentralrepoatatechnicallevel).Wewillrefertothis
repoasorigin,sincethisnameisfamiliartoallGitusers.

Eachdeveloperpullsandpushestoorigin.Butbesidesthecentralizedpushpullrelationships,eachdevelopermayalsopullchangesfrom
otherpeerstoformsubteams.Forexample,thismightbeusefultoworktogetherwithtwoormoredevelopersonabignewfeature,before
pushingtheworkinprogresstooriginprematurely.Inthefigureabove,therearesubteamsofAliceandBob,AliceandDavid,andClairand
David.

Technically,thismeansnothingmorethanthatAlicehasdefinedaGitremote,namedbob,pointingtoBobsrepository,andviceversa.

The main branches


Atthecore,thedevelopmentmodelisgreatlyinspiredbyexistingmodelsoutthere.Thecentralrepo
holdstwomainbrancheswithaninfinitelifetime:
master
develop

ThemasterbranchatoriginshouldbefamiliartoeveryGituser.Paralleltothemasterbranch,
anotherbranchexistscalleddevelop.

Weconsiderorigin/mastertobethemainbranchwherethesourcecodeofHEADalwaysreflectsa
productionreadystate.

Weconsiderorigin/developtobethemainbranchwherethesourcecodeofHEADalwaysreflectsa
statewiththelatestdelivereddevelopmentchangesforthenextrelease.Somewouldcallthisthe
integrationbranch.Thisiswhereanyautomaticnightlybuildsarebuiltfrom.

Whenthesourcecodeinthedevelopbranchreachesastablepointandisreadytobereleased,allof
thechangesshouldbemergedbackintomastersomehowandthentaggedwithareleasenumber.
Howthisisdoneindetailwillbediscussedfurtheron.

Therefore,eachtimewhenchangesaremergedbackintomaster,thisisanewproductionreleasebydefinition.Wetendtobeverystrictat
this,sothattheoretically,wecoulduseaGithookscripttoautomaticallybuildandrolloutoursoftwaretoourproductionserverseverytime
therewasacommitonmaster.

nvie.com/posts/a-successful-git-branching-model/ 2/7
5/8/13 A successful Git branching model nvie.com

Supporting branches
Nexttothemainbranchesmasteranddevelop,ourdevelopmentmodelusesavarietyofsupportingbranchestoaidparalleldevelopment
betweenteammembers,easetrackingoffeatures,prepareforproductionreleasesandtoassistinquicklyfixingliveproductionproblems.
Unlikethemainbranches,thesebranchesalwayshavealimitedlifetime,sincetheywillberemovedeventually.

Thedifferenttypesofbrancheswemayuseare:
Featurebranches
Releasebranches
Hotfixbranches

Eachofthesebrancheshaveaspecificpurposeandareboundtostrictrulesastowhichbranchesmaybetheiroriginatingbranchandwhich
branchesmustbetheirmergetargets.Wewillwalkthroughtheminaminute.

Bynomeansarethesebranchesspecialfromatechnicalperspective.Thebranchtypesarecategorizedbyhowweusethem.Theyareof
courseplainoldGitbranches.

Feature branches

Maybranchofffrom:develop
Mustmergebackinto:develop
Branchnamingconvention:anythingexceptmaster,develop,release-*,orhotfix-*

Featurebranches(orsometimescalledtopicbranches)areusedtodevelopnewfeaturesfortheupcomingoradistant
futurerelease.Whenstartingdevelopmentofafeature,thetargetreleaseinwhichthisfeaturewillbeincorporatedmay
wellbeunknownatthatpoint.Theessenceofafeaturebranchisthatitexistsaslongasthefeatureisindevelopment,
butwilleventuallybemergedbackintodevelop(todefinitelyaddthenewfeaturetotheupcomingrelease)ordiscarded
(incaseofadisappointingexperiment).

Featurebranchestypicallyexistindeveloperreposonly,notinorigin.

Creating a feature branch


Whenstartingworkonanewfeature,branchofffromthedevelopbranch.

$ git checkout -b myfeature develop


Switched to a new branch "myfeature"

Incorporating a finished feature on develop


Finishedfeaturesmaybemergedintothedevelopbranchdefinitelyaddthemtotheupcomingrelease:

$ git checkout develop


Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

The--no-ffflagcausesthemergetoalwayscreateanewcommitobject,evenifthemergecouldbeperformedwithafastforward.This
avoidslosinginformationaboutthehistoricalexistenceofafeaturebranchandgroupstogetherallcommitsthattogetheraddedthefeature.
Compare:

nvie.com/posts/a-successful-git-branching-model/ 3/7
5/8/13 A successful Git branching model nvie.com

Inthelattercase,itisimpossibletoseefromtheGithistorywhichofthecommitobjectstogetherhaveimplementedafeatureyouwouldhave
tomanuallyreadallthelogmessages.Revertingawholefeature(i.e.agroupofcommits),isatrueheadacheinthelattersituation,whereasit
iseasilydoneifthe--no-ffflagwasused.

Yes,itwillcreateafewmore(empty)commitobjects,butthegainismuchbiggerthatthatcost.

Unfortunately,Ihavenotfoundawaytomake--no-ffthedefaultbehaviourofgit mergeyet,butitreallyshouldbe.

Release branches
Maybranchofffrom:develop
Mustmergebackinto:developandmaster
Branchnamingconvention:release-*

Releasebranchessupportpreparationofanewproductionrelease.Theyallowforlastminutedottingofisandcrossingts.Furthermore,they
allowforminorbugfixesandpreparingmetadataforarelease(versionnumber,builddates,etc.).Bydoingallofthisworkonarelease
branch,thedevelopbranchisclearedtoreceivefeaturesforthenextbigrelease.

Thekeymomenttobranchoffanewreleasebranchfromdevelopiswhendevelop(almost)reflectsthedesiredstateofthenewrelease.At
leastallfeaturesthataretargetedforthereleasetobebuiltmustbemergedintodevelopatthispointintime.Allfeaturestargetedatfuture
releasesmaynottheymustwaituntilafterthereleasebranchisbranchedoff.

Itisexactlyatthestartofareleasebranchthattheupcomingreleasegetsassignedaversionnumbernotanyearlier.Upuntilthatmoment,
thedevelopbranchreflectedchangesforthenextrelease,butitisunclearwhetherthatnextreleasewilleventuallybecome0.3or1.0,until
thereleasebranchisstarted.Thatdecisionismadeonthestartofthereleasebranchandiscarriedoutbytheprojectsrulesonversion
numberbumping.

Creating a release branch


Releasebranchesarecreatedfromthedevelopbranch.Forexample,sayversion1.1.5isthecurrentproductionreleaseandwehaveabig
releasecomingup.Thestateofdevelopisreadyforthenextreleaseandwehavedecidedthatthiswillbecomeversion1.2(ratherthan1.1.6
or2.0).Sowebranchoffandgivethereleasebranchanamereflectingthenewversionnumber:

$ git checkout -b release-1.2 develop


Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

Aftercreatinganewbranchandswitchingtoit,webumptheversionnumber.Here,bump-version.shisafictionalshellscriptthatchanges
somefilesintheworkingcopytoreflectthenewversion.(Thiscanofcoursebeamanualchangethepointbeingthatsomefileschange.)

nvie.com/posts/a-successful-git-branching-model/ 4/7
5/8/13 A successful Git branching model nvie.com

Then,thebumpedversionnumberiscommitted.

Thisnewbranchmayexistthereforawhile,untilthereleasemayberolledoutdefinitely.Duringthattime,bugfixesmaybeappliedinthis
branch(ratherthanonthedevelopbranch).Addinglargenewfeatureshereisstrictlyprohibited.Theymustbemergedintodevelop,and
therefore,waitforthenextbigrelease.

Finishing a release branch


Whenthestateofthereleasebranchisreadytobecomearealrelease,someactionsneedtobecarriedout.First,thereleasebranchis
mergedintomaster(sinceeverycommitonmasterisanewreleasebydefinition,remember).Next,thatcommitonmastermustbetaggedfor
easyfuturereferencetothishistoricalversion.Finally,thechangesmadeonthereleasebranchneedtobemergedbackintodevelop,sothat
futurereleasesalsocontainthesebugfixes.

ThefirsttwostepsinGit:

$ git checkout master


Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2

Thereleaseisnowdone,andtaggedforfuturereference.
Edit:Youmightaswellwanttousethe-sor-u <key>flagstosignyourtagcryptographically.

Tokeepthechangesmadeinthereleasebranch,weneedtomergethosebackintodevelop,though.InGit:

$ git checkout develop


Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

Thisstepmaywellleadtoamergeconflict(probablyeven,sincewehavechangedtheversionnumber).Ifso,fixitandcommit.

Nowwearereallydoneandthereleasebranchmayberemoved,sincewedontneeditanymore:

$ git branch -d release-1.2


Deleted branch release-1.2 (was ff452fe).

Hotfix branches

Maybranchofffrom:master
Mustmergebackinto:developandmaster
Branchnamingconvention:hotfix-*

Hotfixbranchesareverymuchlikereleasebranchesinthattheyarealsomeanttoprepare
foranewproductionrelease,albeitunplanned.Theyarisefromthenecessitytoact
immediatelyuponanundesiredstateofaliveproductionversion.Whenacriticalbugina
productionversionmustberesolvedimmediately,ahotfixbranchmaybebranchedofffrom
thecorrespondingtagonthemasterbranchthatmarkstheproductionversion.

Theessenceisthatworkofteammembers(onthedevelopbranch)cancontinue,while
anotherpersonispreparingaquickproductionfix.

Creating the hotfix branch

nvie.com/posts/a-successful-git-branching-model/ 5/7
5/8/13 A successful Git branching model nvie.com

Hotfixbranchesarecreatedfromthemasterbranch.Forexample,sayversion1.2isthecurrentproductionreleaserunningliveandcausing
troublesduetoaseverebug.Butchangesondevelopareyetunstable.Wemaythenbranchoffahotfixbranchandstartfixingtheproblem:

$ git checkout -b hotfix-1.2.1 master


Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

Dontforgettobumptheversionnumberafterbranchingoff!

Then,fixthebugandcommitthefixinoneormoreseparatecommits.

$ git commit -m "Fixed severe production problem"


[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)

Finishingahotfixbranch

Whenfinished,thebugfixneedstobemergedbackintomaster,butalsoneedstobemergedbackintodevelop,inordertosafeguardthatthe
bugfixisincludedinthenextreleaseaswell.Thisiscompletelysimilartohowreleasebranchesarefinished.

First,updatemasterandtagtherelease.

$ git checkout master


Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2.1

Edit:Youmightaswellwanttousethe-sor-u <key>flagstosignyourtagcryptographically.

Next,includethebugfixindevelop,too:

$ git checkout develop


Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

Theoneexceptiontotherulehereisthat,whenareleasebranchcurrentlyexists,thehotfixchangesneedtobemergedintothat
releasebranch,insteadofdevelop.Backmergingthebugfixintothereleasebranchwilleventuallyresultinthebugfixbeingmergedinto
developtoo,whenthereleasebranchisfinished.(Ifworkindevelopimmediatelyrequiresthisbugfixandcannotwaitforthereleasebranchto
befinished,youmaysafelymergethebugfixintodevelopnowalreadyaswell.)

Finally,removethetemporarybranch:

$ git branch -d hotfix-1.2.1


Deleted branch hotfix-1.2.1 (was abbe5d6).

Summary
Whilethereisnothingreallyshockingnewtothisbranchingmodel,thebigpicturefigurethatthispostbeganwithhasturnedouttobe
tremendouslyusefulinourprojects.Itformsanelegantmentalmodelthatiseasytocomprehendandallowsteammemberstodevelopa
sharedunderstandingofthebranchingandreleasingprocesses.

AhighqualityPDFversionofthefigureisprovidedhere.Goaheadandhangitonthewallforquickreferenceatanytime.

Update:Andforanyonewhorequestedit:heresthegitflowmodel.src.keyofthemaindiagramimage(AppleKeynote).

nvie.com/posts/a-successful-git-branching-model/ 6/7
5/8/13 A successful Git branching model nvie.com

Gitbranchingmodel.pdf

Ifyouwanttogetintouch,I'm@nvieonTwitter.

VincentDriessenisanindependentPythonsoftwareengineerandconsultantfromtheNetherlands.Youmayhirehim.

nvie.com/posts/a-successful-git-branching-model/ 7/7

Вам также может понравиться