Trunk-based development (TBD) can reduce complexity and speed up your game delivery, but it does come with its challenges. This session will run through the history of the 'Trunk Based Development' branching model, its modern usage in big enterprises, and how management and technical stakeholders can benefit from it.
In this session, you will learn:
The challenges associated with trunk-based development
How continuous integration can help
Why a "Single Source of Truth" is an important foundation to TBD
2. Challenges in Games Development
• Why is Games Development so hard?
– Besides the obvious I mean …
• Average AAA game:
– 100 of thousands of files
– 1 TB+ source code and assets at HEAD
– 50GB + changes a day
– 100+ Team size
3. Consequences
• Continuous integration
– Builds take minutes (incremental) to hours (full)
– Smoke tests?
– Full tests?
• Who broke the build?
• HEAD is not stable!
4. Coding practices compared
• Different ways to organise your sources
• There is no single best way
– Team size
– Target platform: Mobile/Console/PC/4K/…
– Rate of change
– Iteration frequency
13. Summary
• Stability versus Agility
• Trunk-based development can offer both
– If supported with the right tools
• Careful with branching of binary assets
– Consider componentisation instead
14. Perforce
• Perforce helps delivery teams build complex products collaboratively,
securely and efficiently.
• Commonly used for…
– Software
– Games
– Electronics
– Animations
– Chipsets
– Medical Devices
– Internet of Things
16. Perforce Helix
Contributors
Consumers
Flexible Workflows
Version control, code reviews,
simple file sharing
Fast and Scalable
From 10 to 10,000+ on a each trunk
Every File
Efficiently handles large, often binary, data
Everywhere
Supports geographically distributed teams
Secure
Granular permissions, theft risk monitoring
Open and Extensible
APIs and integration hooks for customization
18. Conclusion
• Trunk-based development is a good thing
• Requires the right tools
• Recommendation
– Componentisation
– Protected release streams
– Keep everything in one repository
Notas do Editor
Trunk based development (TBD): single shared codeline for the whole team
Every change is immediately visible to all other members in the team. One famous proponent of TBD is Paul Hammond
(http://paulhammant.com/2013/04/05/what-is-trunk-based-development/). TBD avoids errors through late merges of long-living development branches.
TBD requires Continuous Integration (CI) to ensure the quality of the trunk.
[Animation] 2 steps
The problem with games (in general) is the size of the assets:
The move to high definition consoles increases the size of the assets into a game manifold
Games used to be delivered on a single Floppy disk! Remember floppy disks? 720KB!
Then came CDs. 700MB. Then came multiple CDs. N * 700MBs
Now most (Windows) games come on DVDs – 4.5 GB per layer, 8.5 GB for a dual-layer DVD-R. Ever installed Shadow of Mordor? 5 DVDs,
or a single 25 GB download – so you better have high speed broadband.
On the console that is a single Blu Ray disk, 25GB as a single layer.
These games are the finished article, all assets compiled and compressed – in HD format. 4K is looming, which will quadruple the space requirements again!
So, what are the consequences?
We cannot do trunk based development – and keep the trunk stable.
What are the alternatives? Let’s have a look at some of these ideas
Caveat: this talk is simply there to show you that there are other ways. By no means do I want to insinuate that I know all the answers.
Your way might be better suited to decide how to code and organize your game.
[Animation]
So here is the naïve version of TBD – a neat linear succession of individual changes, at the end of which is a stable release.
Alas, as your developers and artists add changes, the picture changes.
Because of the time it takes to build and test each check, you cannot hold of the submit of a change until it is verified – or no one can ever submit any changes.
This means that any game studio that uses a single code line for coding their game will wind up with a pointer to the last stable verified version, while the head is most likely broken.
[Animation]
So what about branching?
Well, short live branches often work quite well, as long as I remember to update the branch and test before I deliver the changes back to the shared trunk.
This is called the merge-down / copy-up protocol (explain depending on the audience)
What about long-lived branches? The problem with long-lived branches is that the trunk moves away from the branch, which makes merging/copying a lengthy
and potentially destabilizing process. This can be addressed by updating the development branch on a regular basis (a rebase), but, neglecting that, merging long-lived branches
can be very painful.
So the alternative is short-lived task or features branches – which avoids the complexity of merging large amounts of history.
Another, and more and more popular way when using trunk-based development, is to add feature toggles, avoiding the need to branch for a new feature completely.
No branching, no merging. But what is merging anyway?
lets have a look at merging two text files. The only way this can be done effectively is with the help of a third file – the base.
This gives rise to the notion of the 3-way merge. When you look at the base and the changes both in source and target (marked in green),
you can see that with the help of the base we can calculate the real changes in both source and target, and merge both files together, leaving only one
real conflict (for D).
Without the base we would have two additional conflicts – making the merge a lot more uncomfortable and potentially error prone.
[Animation]
And for binary assets? For the majority of file types merging the files will be impossible – there simply is no tool out there that can calculate the difference of an arbitrary set of binary files in a meaningful (i.e. mergeable) way.
Where does this leave us for a development shared across a large team?
<click>
Locking? The locking workflow is extremely useful here, since the alternative is that two artists touch the same file and one of them will loose all their work – since their efforts cannot be merged.
<click>
Across branches?
Locking across branches does not work – and not that people have not tried that. Perforce has many requests to make locking across branches possible – and the answer is always the same:
What do mean by locking across branches?
See, if I change and submit one file in my development branch, the lock gets removed – that is the workflow of a lock. If someone else has the same file branched into her development branch before I modified this file – and then checks the file out after me and submits it, there is no lock anymore, so both our modifications still clash – and one of us will loose all work.
One way to solve this conundrum if you still want to use branching is to split out the binary files into a separate codeline.
That is: break down the game into its components and develop each part separately.
There are two essential ways to do that:
keeping text and binary source files in a single trunk, but filtering out the files depending on the user. So artists would get only the binary assets (or a subset thereof) and maybe a compiled game engine to test the resultDevelopers might get a compiled set of the binary assets or only the text file.Each file, whether text or binary asset, when submitted, appears directly in the shared trunk
totally separate trunks for code and assets, importing the required files (or compiled artifacts) as needed
Despite the separation, you should still have full control over the whole project, since each individual component should be stored in a central repository – the single source of truth
There is an alternative to all this – and Frank Campagner from Guerrilla Games has talked about this at the Perforce Merge conference 2014:
They tried different approaches but in the end came up with a single trunk but with a twist – a separation between the trunk and the stable version.
Instead of just simply marking a stable version on the trunk, changes (bundled by features) are promoted through a tool written by Guerrilla Games.
This tool lists all eligible features together with their testing status. Once a feature has passed all tests it can be promoted to the release branch – which
itself is never touched directly – only through a controlled release.
Testers and interested parties can then use any version of the release branch – every single instance has passed all tests thrown at it. This way Guerrilla Games have a releasable
version at least every week.
Besides the different ways to organize your code lines for games, one method you should definitely adopt:
Use a separate branch for your milestones.
Why? Because you will probably find that you need to take shortcuts for your milestone and introduce some hacks to get the game into a state it can be demonstrated. This hacks have a tendency to stay behind if you do this in the trunk – so separate the milestone into its own branch, fix the version there, then decide which of this changes are worthwhile keeping and which changes should be better be left behind.
What do branches give us?
Talk about virtual streams as well as a way to keep everything in a single trunk and yet be able to work only on a small subset.