Git branching strategy for Agile project
I have a project that is located in Git Stash Repository. The code will be deployed in four environments(Dev, Test, Stage and Prod). We follow Agile methodology. So dev team works for both Release activities and Non Release( Future Release) activities. I have to create branches based on this requirement. Below is my plan.
Three stable branches: master, release and develop.
master is the default branch. develop will be created from master. release will be created from develop
feature branches –> they will be created from develop. each developer has one feature branch and they merge the code into develop branch once done. so dev environment deployment will happen from develop branch.
if changes need to go Test environment, we have two ways here. one is merge the develop branch with release branch( Test environment deployment will happen from release branch). We can not implement this since develop branch may have both release and non release changes.
another one way is merge the feature branches directly into release branch. so that each developers changes can be merged into release branch. I am not sure whether i can implement this method. Can someone please tell me if this way will work? is there any alternate way to handle this situation.
master branch—> develop branch –> release branch
develop branches — feature branch1 | feature branch2 | feature branch3
develop branch for –> dev deployments
release branch for –> test deployments
master branch for –> stage and prod deployments
I can not merge develop branch into release branch. Since develop branch has some non- release changes as well. I need only release changes on release branch. can feature branches be merged into release branch directly? What is the best approach here?
One Solution collect form web for “Git branching strategy for Agile project”
it sounds to me like, you are very close to choosing Git Flow. Actually, if I’m not mistaken, this is already your base from the strategy, you describe. Which is great.
I’m hearing your main concern is, that you want a non-release “develop” branch, sort of like a “just trying stuff out, might not compile” environment/branch. Git flow indeed favours a “flow” towards production. I.e. once anything is merged from its feature-branch into the develop-branch, it’s pretty much scheduled for next (non-emergency) release.
Git flow’s suggestion on how to handle this, is to not merge a task/feature into develop, until it’s probably ready enough to go into next staging/prod-release with maybe a few fixes. In git flow, you would always merge with non-fast forward (
git merge --no-ff FEATURE_BRANCH_NAME) so that if you are getting near a staging/prod-release, and this feature cannot get ready, you would reverse-merge the (single) merge-commit, thus removing it from the develop or release-branch.
I suspect a longer discussion about this, but just to pitch, I see 2 possible ways to meet your ideas:
1) Have 2 develop-branches: one for development, develop branch, that will soon be sceduled for staging- and prod-release after some QA or whatever. And one for experimental stuff, that will go to a dev/test-environment (e.g. through continuous deployment). Let’s call it long-term-develop (this is a bad and too long name imo, so make a better one, or your team will hate you 🙂 ).
- develop branch should often be merged into long-term-develop branch, to always keep it updated.
- You would probably need 2 develop-environments to test, 1 for each of the branches.
- Danger: branches created from long-term-develop that are (perhaps by mistake) merged into develop could drag more not-ready stuff into develop branch. Solution for this could be to 1) merge feature-branch as non-fastforward into long-term-develop and 2) cherry-pick merge this commit into develop. But this is error-prone and kind of complicated, and 1 wrong merge could screw up entire develop branch, polluting it with stuff not ready for staging/production.
2) Have just 1 develop branch (as you suggest) and create release-branches from master
This is probably by far the easiest way. It takes a little more effort from each developer, but is less error prone.
Procedure would be:
- At each beginning of a sprint/development-cycle, release-manager creates the next release-branch based off master. E.g. release-sprint-42 which, when created, equals master branch.
- Developers create feature-branches with base from develop. They merge feature-branch to develop once it’s ready for testing, et.c. Like you currently suggest.
- If feature is “correct” and working, the merge-commit that was created from merging the feature-branch into develop is cherry-picked with the
-moption into release-sprint-42, e.g.
git cherry-pick -m 1 COMMIT_HASH. Here it’s really important to know, which parent you are picking (in my example parent 1. Develops should read and understand http://git-scm.com/docs/git-cherry-pick).
- Danger could be, that a feature working in develop branch might not work in release-sprint-42 branch, because of missing dependencies. This, thank God, is why we have staging environments and internal deadlines 🙂
- Cherry-picking is not the easiest thing to do. But definitely the best way to try to avoid dragging unwanted code through a merge into a wrong branch.
Which is the best choice for you, depends on how you are developing. If you have 2 tracks, like “daily support-stuff” and “my big feature scheduled for release this December”, you might go for 2 branches. If the long-term development is not 1 but several things and an on-going thing (i.e. if you usually have a lot of tasks, that span over multiple sprints/cycles), I would go for option 2.
Ideally, though, I would per default recommend a strategy, where stuff is broken down into small enough pieces and sprints are big enough, that a task/feature usually can be concluded (i.e. merged and deployed!) within 1 sprint. But from experience I know, that wishful thinking seldomly can be implemented 🙂
1 last thing: I would REALLY really really encourage you to not have 1 release branch (perpetual), but to create a new release-branch for each sprint/cycle, like release-sprint-42, release-sprint-43, et.c. (whether you base it off develop-branch in ideal git flow or off master-branch in the second scenario, I’ve suggested). Having perpetual release-branches often in my experience leads to missing stuff, merge-problems and other badness. Other than that, master and develop should be perpetual-branches.
Looking forward to this discussion 🙂