Minimum setup for efficient DevOps, part 1
Git your source control
This is part 1 in a series describing a minimum setup for a modern DevOps culture, for mature organizations that have not yet embraced it.
Use Source Control
If you are using source control, skip next paragraph.
If you are not using source control, and choose not to, I am sorry, I cannot help you. Start using source control, or stop reading. Choose Git and skip the next section.
Use Git Source Control
If you are using something other then Git based source control, abandon it, switch to Git. I know, I know, TFS is hard to let and there is a lot to say for its simplicity and forced merges. The world has moved on, Git is now cool, get over it. Anyway, with some discipline (more on that later) all will be well.
OK, so now we are all on the same page — we are use Git, and are very happy about it.
Although “git” means “unpleasant person” in British English slang so perhaps we should be slightly offended but it was named by a self professed “egotistical bastard” so let’s just move on.
How to use Git
There are various ways of using Git. I will not spend any time comparing the method as there is plenty of that on the web already. I will share with you a simple version of GitFlow since it is a good choice for a organization moving from a more transitional approach. Ideas of releases and testing are maintained. It has just the things you have to get right about using Git, a few things that you must stick to religiously or fail. Purists will complain and will push for more strict methods — ignore them. If you get just this right, you will do well. Let’s call it “Greg Flow” because I too am an “egotistical bastard”.
If you are new to Git/source control, take the time now to learn the basics, then come back.
The “Greg Flow”
Have 1 main branch where your “current” code lives. Some call it master, some dev branch, some have both. If you are confused at this point, that means you should stick to just 1 main branch and call is “master”. Read this in a couple of month and re-evaluate your main branch strategy.
How to handle changes
Whenever you need to make a change, any change, you never, ever do it directly on the main branch. You create your own separate branch, off the main branch just for this change(1). Call it “feature” branch. You apply your changes to this branch, and test your code there too. Sometimes your change takes minutes, sometimes days [If days, make sure to sync your branch with master daily (2)].
Once you are done with your changes, you must merge your changes to the main branch. Yes, but not so fast! First, you must make sure that no one sneak in changes to the main branch, since you created your feature branch, which could cause conflict/errors. You must “sync-up” your branch, meaning bring in (aka merge) the latest code in the main branch to your branch. Compile and test your code again. Now merge back to the main branch? Almost! but first, you create a Pull Request. Pull Request is basically an invitation for people to mess with your head — other developers can easily see all the changes you want to make, and can do a code review to make sure your changes do not suck, badly.
Typically, you would setup your source control so that a pull request require one or more developers to review and “approve” the changes. Once approved, your code is finally merged back to the master branch, and you are done. Also, you should configure your source control system such that changes to the main branch can only go in via pull request from feature branches thus ensuring this process is followed.
Doing pull request approval is not absolutely required for my minimal-use-of-git approach, but is is recommended. However, I would urge you to do it right or do not bother at all.
How to handle deployment
This can be made a lot more fancy but we are taking baby steps so start just with this: When all (or most of) the changes are in the main branch, create a ReleaseX branch, off the main branch. This will be the code that is getting ready to be released shortly. Exactly how to handle releasing this code will be the subject on another post. Suffices to say for now, this “ReleaseX” (where X stands for some kind of release version or identifier) will be the code that is to be released.
If bugs are found in the release branch, they will follow the same process as other changes — feature branch off the release branch, pull request etc. Once a release is made, the branch is locked and kept around. Patches are applied to this branch like any other changes. Any changes in this release branch, have to be merged back to the main branch.
Sounds complicated? If you are new to Git, then yea… but you will get the hang of it and soon realize it is really not that bad at all.
This is the minimal Git setup you must have, on your path towards an efficient DevOps. If this is all new to you, I suggest you implement and use this for a few releases, then read up on git flow or github flow and the improvements to this will become clear. If you are feeling brave, you can go right for the holy grail. I will try to coerce my old colleague to share his experience of taking this to its maximum, and final setup, and link to his article.
~~~
footnotes
(1) regarding feature branches — creating a branch for just one change. This is recommended, works very nicely vast majority of the time. When you create the pull request, reviewers can easily understand the purpose of your changes as it is related to just one work order. If you squeeze multiple different, unrelated changes, into one branch, this breaks down a bit. However, what if you do have multiple, distinct changes yet changes that build on top of each other? ie, changes that depend on one another? You cannot create FeatureA branch of the main branch and FeatureB branch of the main because FeatureB needs changes implemented in FeatureA. So does your FeatureA branch get two changes, A&B? or do you create a FeatureB branch off-of FeatureA? I have had debates with people who argue for the latter but I do not not recommended it. In such a case, put both changes A and B in FeatureA branch. Better yet, call the branch FeatureA_B
(2) the unintended benefit and achilles’ heel of a centralized source control like TFS, was that you often shared a development branch and your feature branch, was your local workspace, which you were encouraged to check in daily, thus “merge” your code daily. In that time, “braking the build” — checking in code that broke the nightly compile of the shared branch — was a capital offence. This forged good practices like daily merge and test on your workspace before checking in your code. With Git, too many developers keep changes on their feature branches isolated for days, or weeks, and then marge back to the main branch, sometimes without even synching main branch changes to the feature branch once. Too often have I see developer in such situations delegating the job of reconciling conflicts to someone else. Git lends its self well to this abuse. The one easy way to eliminate this, is to have the developers merge the parent branch to their feature branch often, at least daily. To my best understanding, this is however, impossible to enforce.