I work on small team with other remote developers on a Rails
application. We are starting to modify our git
workflow. We have thought about a branching structure like below:
(dev) -> (qa) -> (stag) -> (master)
But some of the developers thought it might be less confusing for new developers who might automatically push to production on master. They thought instead to have everyone work on master and create a separate branch for production.
(master) -> (qa) -> (stag) -> (prod)
I was taught you want to keep master deployable and not use it as development and from previous places where I’ve worked master is always meant to be deployable for production.
What would be some of the disadvantages of using a branching structure where master is actively used for development and a separate prod branch is what you use for deployments?
4
There are neither any advantages nor disadvantages to this approach. The reason I say this is simple: to Git, it makes no difference if you develop from master or release from master. You don’t even need to release branches; you could tag an arbitrary commit and release that, instead.
The real trouble here is one of process and procedure. The more senior devs that are concerned that doing it in one way will confuse the newer devs need to be prepared to invest the time to explain what the release model is and why it’s that way.
So long as everyone understands that master is for development, and some other arbitrary branch is for releases, and the work to maintain this is done, then there shouldn’t be any problems with this approach.
3
I can see your dilemma. I had it too, until I unlearned what I always assumed about master.
I was taught you want to keep master deployable and not use it as development and from previous places where I’ve worked master is always meant to be deployable for production.
From Git’s documentation / book – Git branching
The “master” branch in Git is not a special branch. It is exactly like any other branch. The only reason nearly every repository has one is that the git init command creates it by default and most people don’t bother to change it.
So, if you have a preferred workflow, and it is difficult to work with it because different developers on the team have different ideas about master
. You might even consider renaming master
to say prod
and use a workflow like below –
(dev) -> (qa) -> (stag) -> (prod)
Here is how you change the master branch name.
I am NOT saying that you must change the master
branch name. But if you have a preferred workflow and it helps to change the master
branch name, do it by all means 🙂
1
I prefer checks over conventions in this case. Every team contains member who are better at getting new features started and other people who are better at stabilizing things for a release.
If you lack the latter, then code reviews will help (often, the more disciplined people will want code reviews anyway).
That’s why we configure our Git repo (we’re using Gitlab) that only certain people can merge pull requests and each developer gets their own private fork of the main repo.
That solves two problems:
-
New developers can’t change the wrong branch (since they can’t push their work directly into the main repo). They might push to
master
on their own repo but that will be fixed when the pull request comes in. -
Code conventions quickly spread through the team since each commit is checked by at least another person who brings their view and knowledge.
It all depends on the overall software development process. Configuration management and how a new version comes to be cannot be defined without knowing about the overall process.
There is the “agile” faction who would opt for a “always working first commit area”. They would run automated build and test facilities constantly against that area and try to have a working system “at all times”.
They would see the (master) -> (release) with maybe 1,2 intermediate steps organization as beneficial.
Then there is the more “classic” faction, which has a process driven by planning and planned integration steps towards milestones, where a “unit of work” release is a planned activity with requirements such as “only release when it is (unit) tested and supposed to fit to the next planned milestone”. There, the planning comprises the versioning of “units of work” and typically they go to lengths to define how the next planned product release is supposed to look like in terms of features and fixes. For the sake of planning, they want to know that what a developer releases is “proper” and a conscious act of committing a unit of work.
That classic approach does not mean necessarily that there are longer times where there is no complete product build is available.
So the “classic” workflow would be: (dev) -> (unit) -> (integration) -> (test/qa) -> (production).
The role of the integrator is to “accept/buy” released units or reject them if they do not fit the needs of the next upcoming release.
It is, on a side note also possible to mix those 2 basic approaches in opportune ways.
From my experience (which was mostly in the area of using the “classic” approach), the “classic” approach worked decently well in projects from about 4-50 people in a team.
I think the second option is better:
(master) -> (qa) -> (stag) -> (prod)
(But see the next section for caveats.)
master
is the original git init
default name.[1] It’s quite natural
to assume that the bulk of the work will be done on a branch with that
name. For that reason I think that it’s backwards that workflows like
“Git Flow” decided that master
is the “production ready” branch while
the new arbitrary name develop
is for active development. Git Flow
would be better if instead of this:
(develop) -> (master)
It used this:
(master) -> (production)
- It’s quite natural to target your PRs against
master
- It’s quite natural to avoid something named
production
for any PR
or branch-off
And likewise for your two alternatives:
(dev) -> (qa) -> (stag) -> (master)
- Here some new contributor might notice
master
first and just assume
that that’s the main branch that you’re supposed to do work against - Of course
dev
has a hint in its name, but it’s somewhat arbitrary
what the new contributors will see first
Git Flow’s influence
Of course Git Flow has already been established for a long time and has
managed (hmph) to condition some people to think of develop
as the
main development branch and master
as the “production” branch. So it
might be the case that dev
is more of a “main branch” hint to some
people than what master
is! So in that case maybe my answer is
wrong. But personally when I see people discuss Git (like on
StackOverflow), they almost always use master
as the stand-in for “our
main branch” and almost never develop
.
Git Flow seems to be more of a fascination of this particular
StackExchange.
Notes
- Now it’s configurable.
main
is also common, in part due to GitHub’s
default.