We all have our favorite source control client. Whether it's SVN, git, Mercurial, you name it.
This thread is not about specific clients. What I want to discuss is the strategies and methodologies you use when working with source control.
Whether it's distributed or centralized, linear or parallel, or any other kind of features, Source Control inevitably comes down to two features: Branching and Labeling.
Labels are pretty straight forward. They are read only representation of your repo at one given state. Commonly, it's used for version labeling (like "v1.0.3"). It's the branching that interests me, and that I will explore in this post.
Note: it could be argued that other features like file locking, merging and forking are crucial features of source control, but those are too tightly linked to the specific client you're using and aren't broad enough for a generic discussion.
When do you create branches? What's on the "main" branch? Where's the latest
stable release? The latest
dev/unstable one? How do you provide support for older versions?
What I will expose next are not to be taken as absolute truth, but rather the strategies I have developed from experience, depending on the situations I'm facing.
Pet projects
Pet projects are very common with the hobbyist programmer. They are projects we do for fun and that took us some time and effort to develop. I develop and maintain
Agros for example.
These projects have common features:
* There is very little need for support for older versions. If I publish version 0.8.3, I don't care about version 0.1.2 anymore.
* They usually have very little number of programmers working on it simultaneously. The need for a sharing (merging) mechanism is real, but not very important.
* These projects tend to be extremely experimental, developers tend to "try" things a lot.
My usual approach is the following:
- Every development happens in a separate branch.
- When I'm satisfied with the result, I merge back in the "main" branch.
- "main" branch usually has the latest developments, and is considered stable.
- Once in a while, when I'm satisfied with the result, I label the latest "main" with an incremental version number".
- Every time I feel like "experimenting", I pull a branch from the latest labeled version. When I'm satisfied with the code I merge back to main (and usually push to github afterwards).
Here's the schema:
________feature _____feature3
/ \ /
main--------------------*--------*-----*---- latest_version
\ / v0.1
\__________feature2
That scheme allows me to pull branches at any time, and start something new
Rolling Releases
This type of development is for teams who are maintaining a constantly available app on their own servers. Web development is a perfect example:
* No need to support older versions, all your users are using your latest version of the software.
* Version won't go into production unless it's really stable.
* There is a need to maintain multiple versions (prod-like, qualification, testing, experimental, ...)
* There's usually more than one developer on the project.
This workflow mirrors the way we do things at work:
- "main" branch mirrors production code at all time. It's the latest
stable release.
- Each dev branches from "main" latest, does his work on a separate branch and commits.
- At the end of each dev cycle, the repo maintainer creates a new "assembly" branch, and merges all the latest developments, until
qualification version is created.
- After all the testing on qualif is done and validated, the version is sent to production. Repo maintainer merges back "assembly" branch into main.
This is how it would look like:
_______________________ASM
/_____dev2__/ / \
/ ________dev1______/ \
/ \
/ \
main--*------------------------------------*------------
v11.0 v12.0
Notice how v12.0 was originally created, tested, qualified and validated in ASM branch, and it went back to main after delivery (the schema doesn't show all the various reworks that happened. But you get the idea).
Software Publisher
A publisher acts differently. Software is not on my server, it's on customer's computer. You have no control over version used. For instance, Microsoft still provides updates for Vista, even though w7 is long published.
Characteristics:
- Heavy emphasis on multiple versions. Even the old ones.
- Multiple developers working on the project.
- Ability to share features across versions (for instance if Word 2010 develops support for new XML standard, you want Word 2007 to get that feature as well).
The way I proceed to doing it would be the following:
- "main" branch has the latest development and is unstable.
-
stable versions are each in one branch. Support for this version happens on the branch.
- Multiple developers work and commit on "main" branch so you have to implement "commit access" (or permissions) policy, where only senior developers are allowed to commit.
Here's the idea:
v1.2.1 v1.2.2
/ /
v1.0.0 v1.2.0--------- v2.0.0
/ / /
-------------------------------------- dev
You can imagine that v1.2.1 and v1.2.2 were developer
after v2.0.0 was published.
Conclusion
In any case, those are just random strategies I have developed after dealing intensely with source control for the past 2 years. For further reading, I strongly recommend
this article by the Daily WTF. It's a pretty cool definition of source control in general.
What are your strategies? How do you proceed with source control? Do you have any interesting schema to share?