5/8/13 A successful Git branching model nvie.
com
A successful Git branching model
[Link]
Published:January05,2010
InthispostIpresentthedevelopmentmodelthatIveintroducedforallofmyprojects(bothatworkandprivate)aboutayearago,andwhich
[Link],butIveneverreallyfoundthetimetodo
sothoroughly,[Link],merelyaboutthebranchingstrategyandreleasemanagement.
ItfocusesaroundGitasthetoolfortheversioningofallofoursourcecode.
Why git?
ForathoroughdiscussionontheprosandconsofGitcomparedtocentralizedsourcecodecontrolsystems,[Link]
[Link],[Link]
[Link]/SubversionworldIcamefrom,merging/branchinghasalwaysbeenconsideredabitscary
(bewareofmergeconflicts,theybiteyou!)andsomethingyouonlydoeveryonceinawhile.
ButwithGit,theseactionsareextremelycheapandsimple,andtheyareconsideredoneofthecorepartsofyourdailyworkflow,[Link]
example,inCVS/Subversionbooks,branchingandmergingisfirstdiscussedinthelaterchapters(foradvancedusers),whileineveryGit
book,itsalreadycoveredinchapter3(basics).
Asaconsequenceofitssimplicityandrepetitivenature,[Link]
[Link]/posts/a-successful-git-branching-model/ 1/7
5/8/13 A successful Git branching model [Link]
aresupposedtoassistinbranching/mergingmorethananythingelse.
Enoughaboutthetools,[Link]
proceduresthateveryteammemberhastofollowinordertocometoamanagedsoftwaredevelopmentprocess.
Decentralized but centralized
Therepositorysetupthatweuseandthatworkswellwiththisbranchingmodel,[Link]
onlyconsideredtobethecentralone(sinceGitisaDVCS,thereisnosuchthingasacentralrepoatatechnicallevel).Wewillrefertothis
repoasorigin,sincethisnameisfamiliartoallGitusers.
[Link],eachdevelopermayalsopullchangesfrom
[Link],thismightbeusefultoworktogetherwithtwoormoredevelopersonabignewfeature,before
[Link],therearesubteamsofAliceandBob,AliceandDavid,andClairand
David.
Technically,thismeansnothingmorethanthatAlicehasdefinedaGitremote,namedbob,pointingtoBobsrepository,andviceversa.
The main branches
Atthecore,[Link]
holdstwomainbrancheswithaninfinitelifetime:
master
develop
[Link],
anotherbranchexistscalleddevelop.
Weconsiderorigin/mastertobethemainbranchwherethesourcecodeofHEADalwaysreflectsa
productionreadystate.
Weconsiderorigin/developtobethemainbranchwherethesourcecodeofHEADalwaysreflectsa
[Link]
[Link].
Whenthesourcecodeinthedevelopbranchreachesastablepointandisreadytobereleased,allof
thechangesshouldbemergedbackintomastersomehowandthentaggedwithareleasenumber.
Howthisisdoneindetailwillbediscussedfurtheron.
Therefore,eachtimewhenchangesaremergedbackintomaster,[Link]
this,sothattheoretically,wecoulduseaGithookscripttoautomaticallybuildandrolloutoursoftwaretoourproductionserverseverytime
therewasacommitonmaster.
[Link]/posts/a-successful-git-branching-model/ 2/7
5/8/13 A successful Git branching model [Link]
Supporting branches
Nexttothemainbranchesmasteranddevelop,ourdevelopmentmodelusesavarietyofsupportingbranchestoaidparalleldevelopment
betweenteammembers,easetrackingoffeatures,prepareforproductionreleasesandtoassistinquicklyfixingliveproductionproblems.
Unlikethemainbranches,thesebranchesalwayshavealimitedlifetime,sincetheywillberemovedeventually.
Thedifferenttypesofbrancheswemayuseare:
Featurebranches
Releasebranches
Hotfixbranches
Eachofthesebrancheshaveaspecificpurposeandareboundtostrictrulesastowhichbranchesmaybetheiroriginatingbranchandwhich
[Link].
[Link]
courseplainoldGitbranches.
Feature branches
Maybranchofffrom:develop
Mustmergebackinto:develop
Branchnamingconvention:anythingexceptmaster,develop,release-*,orhotfix-*
Featurebranches(orsometimescalledtopicbranches)areusedtodevelopnewfeaturesfortheupcomingoradistant
[Link],thetargetreleaseinwhichthisfeaturewillbeincorporatedmay
[Link],
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,[Link]
avoidslosinginformationaboutthehistoricalexistenceofafeaturebranchandgroupstogetherallcommitsthattogetheraddedthefeature.
Compare:
[Link]/posts/a-successful-git-branching-model/ 3/7
5/8/13 A successful Git branching model [Link]
Inthelattercase,itisimpossibletoseefromtheGithistorywhichofthecommitobjectstogetherhaveimplementedafeatureyouwouldhave
[Link]([Link]),isatrueheadacheinthelattersituation,whereasit
iseasilydoneifthe--no-ffflagwasused.
Yes,itwillcreateafewmore(empty)commitobjects,butthegainismuchbiggerthatthatcost.
Unfortunately,Ihavenotfoundawaytomake--no-ffthedefaultbehaviourofgit mergeyet,butitreallyshouldbe.
Release branches
Maybranchofffrom:develop
Mustmergebackinto:developandmaster
Branchnamingconvention:release-*
[Link],they
allowforminorbugfixesandpreparingmetadataforarelease(versionnumber,builddates,etc.).Bydoingallofthisworkonarelease
branch,thedevelopbranchisclearedtoreceivefeaturesforthenextbigrelease.
Thekeymomenttobranchoffanewreleasebranchfromdevelopiswhendevelop(almost)[Link]
[Link]
releasesmaynottheymustwaituntilafterthereleasebranchisbranchedoff.
[Link],
thedevelopbranchreflectedchangesforthenextrelease,butitisunclearwhetherthatnextreleasewilleventuallybecome0.3or1.0,until
[Link]
numberbumping.
Creating a release branch
[Link],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"
$ ./[Link] 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,[Link],[Link]
somefilesintheworkingcopytoreflectthenewversion.(Thiscanofcoursebeamanualchangethepointbeingthatsomefileschange.)
[Link]/posts/a-successful-git-branching-model/ 4/7
5/8/13 A successful Git branching model [Link]
Then,thebumpedversionnumberiscommitted.
Thisnewbranchmayexistthereforawhile,[Link],bugfixesmaybeappliedinthis
branch(ratherthanonthedevelopbranch).[Link],and
therefore,waitforthenextbigrelease.
Finishing a release branch
Whenthestateofthereleasebranchisreadytobecomearealrelease,[Link],thereleasebranchis
mergedintomaster(sinceeverycommitonmasterisanewreleasebydefinition,remember).Next,thatcommitonmastermustbetaggedfor
[Link],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,[Link]:
$ 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,[Link]
[Link]
productionversionmustberesolvedimmediately,ahotfixbranchmaybebranchedofffrom
thecorrespondingtagonthemasterbranchthatmarkstheproductionversion.
Theessenceisthatworkofteammembers(onthedevelopbranch)cancontinue,while
anotherpersonispreparingaquickproductionfix.
Creating the hotfix branch
[Link]/posts/a-successful-git-branching-model/ 5/7
5/8/13 A successful Git branching model [Link]
[Link],sayversion1.2isthecurrentproductionreleaserunningliveandcausing
[Link]:
$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./[Link] 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
[Link].
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,[Link]
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
[Link]
sharedunderstandingofthebranchingandreleasingprocesses.
[Link].
Update:Andforanyonewhorequestedit:[Link](AppleKeynote).
[Link]/posts/a-successful-git-branching-model/ 6/7
5/8/13 A successful Git branching model [Link]
[Link]
Ifyouwanttogetintouch,I'm@nvieonTwitter.
[Link].
[Link]/posts/a-successful-git-branching-model/ 7/7