We have a scenario where we'd like to use two branches in our git workflow, otherwise known as develop
and master
.
The current flow is as follows:
- Create
feat-branch
- this branch will be based off ofmaster
. - Make your changes in
feat-branch
, then finally commit your changes, and push them upstream to the remotefeat-branch
. - Finally, the goal is you will eventually make two Pull Requests (via GitHub). One will be:
develop <- feat branch
and the other will bemaster <- feat branch
This methodology works perfectly fine for merging things into the master branch since the feature branch is already branching off of the master branch (aside from having to git pull origin master
every now and then when you are out of date - but this is expected (I personally like to rebase my feature branches as well)).
However, the idea is you will be making a Pull Request to develop
first (before you even make a secondary Pull Request to merge to master
).
Merging to the develop
branch becomes dicey at this point because each contributor is effectively making the same exact PR to both develop and master, which is creating different merge commit hashes in each respective branch with the same changes.
However, since everyone is branching off of master, this means those merge commits that end up in master eventually get merged back into the develop branch over time... this causes PRs to have erroneous differences being displayed which essentially say the same changes are being made by another person.
I'm guessing this is a mix of how commit hashes work in conjunction with the fact that every merge commit that is created after a Pull Request is merged into master ends up being included in a PR to the develop branch.
At this point I'm kind of just looking for maybe some sort of general direction or ideas regarding resolution, whether it be an entirely different way to approach the 2 branch model or something different altogether.
2 Answers 2
To me it sounds from your description like your develop
branch is actually an integration and testing (or QA) branch; and that your master
branch is actually your production (or release) branch.
If so then your feature branches should be forked from develop
, and the only person merging to master
should be your release manager, and those merges should only ever come from the develop
branch.
Either stick to develop
as your primary branch, or gate pull requests to master
with a test suite.
You are currently using master
to represent your working, tested software, and develop
to integrate different feature branches.
Your current process fails to do that well. By merging the feature branch separately into develop
and master
, there's the risk that the two target branches don't end up with the exact same state. Furthermore, due to the way Git works, merges become increasingly tedious as the branches diverge.
One way to address this is to only merge features into develop
. When you feel ready, the current state of develop
can be merged into master
. This is effectively the Nvie Git-Flow, with all of its advantages and disadvantages. The Git-Flow is well suited for software with big, infrequent releases that need to be supported for some time in parallel.
A different approach is to merge all features directly into master
. This is very easy and straightforward, but requires that the changes don't break anything – master
should always be in a releasable state. The same people who invented Continuous Integration were also big on automated testing, to the degree that the two are now effectively synonymous. GitHub popularized pull-request based patterns, where the PR gives opportunity for manual reviews and automated testing.
Such PR-based approaches are a good fit when you have frequent small releases, especially in an SaaS or web context, and when bugs in the released version tend to be low-impact so that they can be fixed in a subsequent release (no hotfixes!). However, this requires a QA culture that has high confidence in the automatic tests. This doesn't necessarily mean 100% unit test coverage, but some integration tests for essential functionality and lints/static analysis to find potential problems. If you already have high converage, checks like "added lines must be covered by tests" can be useful.
Pull-request based approaches run into problems with large features that have diverged a lot from master
, and with WIP changes that are not in releasable state. However, you can use refactoring patterns and feature toggles to make gradual changes without breaking anything and to only enable risky functionality once it feels ready. Sticking to such safe patterns and writing suitable tests requires some discipline and competency, though.
master
branch and axing the other branch altogether. The goal of the 2 branch model was to ensure we had some sort of buffer before something went tomaster
. Ideally you'd make a PR to develop ,test the changes, then eventually make the same PR from your feature branch to master.develop
andmaster
, usually) there is arelease
branch in between the two. You cut therelease
branch fromdevelop
, test it, tweak it, and then mergerelease
intomaster
in one fell swoop. How often do you merge feature branches, and how often to you release / deploy to production?master
are not allowed unless they're urgent bug fixes.