Git is a version control system at the heart of almost all software development—it’s used to store and track changes to the code you write. When working in teams, having an easy-to-follow workflow that works for your business is crucial to fast development.
Better Repository Organization, Faster Development
With the rise of easy-to-use automation pipelines like Jenkins, many companies are beginning to do continuous integration & delivery (CI/CD), with changes from developers being merged into the repo often, usually shipping a product on a weekly rather than monthly schedule.
This kind of speed puts a lot of stress on your organization, especially when it comes to Git. If you have 50 people, all trying to make changes to the same master branch, you’re going to run into problems with frequent merge conflicts.
Luckily, Git provides the ability to make branches, and choose when you want to merge code, which every team should be using to organize their development. Getting under control of your Git workflow will, at the very least, save you and your teammates from wasting time googling more Git issues.
Feature And Develop Branches
There are two big problems Git branches work to help solve—keeping your internal teams in sync, and maintaining your public release.
When you start a branch in Git, new commits will be made on that branch, rather than master. This can be useful for keeping track of individual progress on a given feature or bugfix; for example, each branch can implement a feature outlined in an issue in a Kanban service, like Jira, Trello, or Github Issues & Projects.
Usually, merging branches is done with pull requests, a feature of hosted Git solutions like Github, where the team requests that master pull from the feature branch, and integrate the changes for everyone. This can be very useful for teams to do QA and unit testing to ensure the branch functions properly before being pushed up the chain.
The other problem is managing your releases—you don’t want to be shipping your customers a copy of your latest internal dev build, as that may be broken by an errant commit.
To solve that, many teams will use a separate branch for releases, and only merge that branch when it’s time to push a new version. This allows multiple commits to be done in the background, on the dev branch between releases.
Another benefit of this model is being able to have separate commits made on the production branch, perhaps providing patches to problems before the next release is ready.
Trunk Based Development
Your branching strategy determines the exact way you use these tools provided to you. There are many different branching strategies made for different kinds of teams.
Trunk based development is close to what team programming should be—quick iteration on the master branch, to push out a viable product quickly. The team makes short-lived feature branches, usually not lasting more than a few days, and often committing straight to master.
It’s called “trunk” because the effect of this makes the master branch the most active and useful branch in the whole repo, like a thick tree trunk that supports everything else. All development is done focused on this branch, which is quick and easy to wrap your head around, making for a good developer experience.
Once ready for release, a new versioned branch is created, for each release. This keeps releases separate from master, and also helps with adding or cherry-picking patches to LTS releases.
This has a lot of benefits, especially for small teams. If you’re working with a handful of senior developers you know, and trust with write permissions to the whole repo, integrating your changes ASAP can really speed up development. After all, it takes away almost all the bureaucracy of constant pull requests and merges—though simple communication with your team is still necessary to prevent stepping on each other’s toes, and you must know at all times what another is working on.
However, this isn’t great organization, as it relies on discipline and good developers to pull it off. It’s really great for getting products out quickly, or to quickly iterate on existing projects, but once you add more junior developers to the project, or get more open-source collaborators, it’s going to start to show its flaws.
Traditional Git Flow
“Git Flow” is a workflow that has worked for many teams. It’s more complicated than trunk-based development’s simple workflow, but it provides a lot of benefits for open-source projects, and large projects with many team members.
In a Git Flow branching strategy, feature branches are longer lived, and the primary focus of daily integration. Teams will work on features until they’re ready for production, and then go through the pull request process to get them approved. There may be any number of features at a time, including ones that live long enough to need rebasing onto more recent master commits.
With Git Flow, access is more restricted, as most developers will not have permission to merge directly onto develop, and of course not on master, and will have to make branches as the primary method of making changes.
Git Flow naturally leaves time for proper code review during the pull request process. It allows conflicts to be handled through PRs, rebasing, and merging, rather than a constantly changing trunk branch. This makes sense for open source, as those branches may be from outsiders, but it also makes sense in large team environments, or for teams delivering monolithic products with many components.
One of the key features of this workflow is the release pattern. When it’s time for a new release, a separate branch is created to prepare. Final bugfixes and patches are done here, then pushed to the actual master branch and given a tag, from which a release can be built.
The key difference is that this master branch is maintained alongside develop. The commits from the release branches are merged back into develop, as well as any hotfixes. This makes develop always the most up to date branch, from which releases are made when they’re stable.
Having this separation makes it easier to manage smaller bug fixes that must release before master is merged with the latest releases. A release branch operates pretty similarly to a feature branch, with the feature being the fact that it’s being marked as a stable release.
Of course, constant pull requests, rebasing, and merging is hard work, and can be tiring if you’re trying to work quickly. But much like static typing or unit tests, it’s worth it in the end to keep things organized and working smoothly all the time.
Choose What’s Right for You
At the end of the day, it’s all about having good team etiquette, and your team may get by just fine with a Git history that looks more like a line than a fancy diagram. If your project is small, or you’re a solo hobbyist, adhering to strict Git standards may be doing you more harm than good.
But if you’re having problems with Git, you may want to try either trunk-based development or Git Flow. At the very least, being conscious of your repository’s organization will help you improve your integration process.