This article will only focus on the branch publishing strategy, and will not involve any project details.
If you want to deeply understand the advantages and disadvantages of GIT and centralized code version management system, you can query on the Internet. This topic has been debated for a long time. As a developer, I prefer GIT. Git really changed developers’ understanding of code merging and branch management. As a person who has used the traditional CVS tools, merging / branching is a relatively terrorist act, which has to be carried out once.
However, GIT’s branch merge and creation operations are very simple, and they are already part of the daily workflow. For example, in CVS books, branching and merging will only be introduced to high-end developers in the last chapter, while in every git book, it will be explained in Chapter 3.
Because of GIT’s simplicity and repeatability in this operation, branch development and merging is no longer a terrible thing. Version control tools should help create and merge branches better.
Let’s not talk about tools, but about development models. The model I’m going to introduce today is essentially a set of processes that each team member follows to manage the software development process.
Decentralization and centralization
In the branch publishing model, we will set up a centralized “truth” warehouse. This warehouse is only a nominal central warehouse (Git is a decentralized warehouse, so technically speaking, this warehouse is not centralized). We mark the warehouse as origin, because the name origin is familiar to all git users.
Each developer pulls and uploads code from origin. Each developer can also pull or build sub code teams from each other’s code warehouses. This method is suitable for large teams, that is, sub teams can develop features on a team branch first, and then submit them to the origin warehouse after the features are stable.
Central warehouse has two branches with permanent life cycle: master and development
The main branch of master in origin repository is very familiar to every git user. The branch that is flush with the master branch is called the development branch.
The origin / Master branch is the main branch of the project, and the head tag of the source code always points to a publishable version on the branch.
We call the origin / development branch another type of main branch, where the code is always in a stable and publishable state. All changes on this branch should be merged into the master branch with a publish label. The specific operation will be described in detail later.
Therefore, every time a change is merged into the master branch, it means that a new release is released. We strictly follow this definition, so in theory, whenever a code is submitted to the master branch, we should use git hook to automatically build and publish the code to the production environment server.
In addition to the main branch master and development, the development process model also uses various auxiliary branches to realize the parallel development among team members, simplify the function development, prepare for production release and quickly repair the faults of production environment. Unlike the main branches, these branches all have a certain life cycle, because they will eventually be deleted.
The types of auxiliary branches include:
- Feature branch
- Release branch
- Fix branch hotfix branch
Each type of branch has a specific goal, and is limited by different constraints, such as which type of branch the branch should be generated from and which type of branch it should be merged into.
However, there is no difference between these branches from the perspective of GIT. They are git branches in the common sense, but we give them different usage semantics.
Source branch: Development Branch
Merge branch: Development Branch
Branch naming specification: Master, development, release-, and hotfix-
Feature branching is to support the development of new functions in the future. At the beginning of feature branch development, the corresponding future release branch may be unknown. The essence of the feature branch is that as long as the feature is still under development, the branch will always exist and will eventually be merged back into the development branch (it is certain that the feature will be released) or abandoned (the development result of the feature does not meet the expectation).
Feature branches generally exist only in the developer’s repository.
Create a property branch
$ git checkout -b myfeature develop Switched to a new branch "myfeature"
Merge the developed features into the development branch
$ git checkout develop Switched to branch 'develop' $ git merge --no-ff myfeature Updating ea1b82a..05e9557 (Summary of changes) $ git branch -d myfeature Deleted branch myfeature (was 05e9557). $ git push origin develop
--no-ffThe tag enables the merge operation to create a new commit record, even if the merge can be quickly merged into the target branch by fast forward. This method avoids the loss of all historical commit records on the feature branch. The comparison is as follows:
In the figure on the right, you can’t see which submission records form the feature branch from git submission history. You need to read all the log messages manually. Rolling back the feature code is a very troublesome thing in the right figure, but through the
--no-ffThe merged left is easier. Although it creates more commit records, the overall advantages outweigh the disadvantages.
Source branch: Development Branch
Merge branches: development branch and master main branch
Branch naming specification: release-*
The release branch supports the preparation for the release of a new production environment. It allows for the final operation before going online. In addition, it allows for minor bug fixes and pre release metadata preparation (version number, build date, etc.). By doing these things on the release branch, the development branch becomes more concise, just receiving new features that will be released in the future.
When the development branch basically reaches the state of publishing a new version, a new publishing branch needs to be created from the development branch. All feature branches that meet the release criteria must be merged into the development branch at this time. However, feature branches that have not yet met the publishing conditions need not be merged into the master branch. They must wait until the end of the publishing branch life cycle before they can be merged into the development branch.
When creating a publish branch, a version number (no earlier than this) will be defined for this release. Until this moment, the development branch for the next release didn’t know whether its next release version number was 0.3 or 1.0. When a release branch is created, the version number of this release will be determined according to the evolution rules of the version number.
Create publishing branch
The publish branch is created in the development branch. For example, suppose the current production environment has a version number of 1.1.5, followed by a major release. At this point, the development branch has reached the requirements of the next release, and we decided that the version is 1.2 (not 1.1.6 or 2.0). Because of the coarseness, we create a branch and add a new version number to the name of the publish branch
$ git checkout -b release-1.2 develop Switched to a new branch "release-1.2" $ ./bump-version.sh 1.2 Files modified successfully, version bumped to 1.2. $ git commit -a -m "Bumped version number to 1.2" [release-1.2 74d9424] Bumped version number to 1.2 1 files changed, 1 insertions(+), 1 deletions(-)
After creating a new branch and switching to it, we start to switch the version number. Here,
bump-version.shIs a virtual shell script that performs some version operations on the published version file (of course, these operations can be done manually). Next, the version operation is committed.
This new branch will exist for a while until the release is fully executed. In the meantime, you can fix bugs on the branch (not on the development branch), but don’t add big new features. They must first be merged into the development branch and then wait for the next publishing node.
End publishing branch
When the publish branch can be published, some operations need to be performed before that. First, the publish branch is merged into the master branch. Then, the code submitted to the master branch must be labeled so that the historical version can be referenced in the future. Finally, the code on the release branch must be merged into the development branch, so that the code on the development branch also contains the content of the release version and the bug fixed.
$ git checkout master Switched to branch 'master' $ git merge --no-ff release-1.2 Merge made by recursive. (Summary of changes) $ git tag -a 1.2
At this point, the publication is complete and tagged for reference.
Then merge the changes into the development branch:
$ git checkout develop Switched to branch 'develop' $ git merge --no-ff release-1.2 Merge made by recursive. (Summary of changes)
In this step, there may be conflicts in the merge operation, which need to be resolved and submitted.
After that, we can delete the publish branch because we no longer need it:
$ git branch -d release-1.2 Deleted branch release-1.2 (was ff452fe).
Fix branch hotfix branch
Source branch: master main branch
Merge branches: development branch and master main branch
Branch naming specification: hotfix-*
The repair branch is very close to the release branch because they are both a branch preparing for the release of the production environment. The reason for the repair branch is that the code in the production environment needs to be changed immediately. When there is a major bug in the production environment version code that needs to be handled immediately, you can pull a repair branch from the corresponding version of the production environment code to handle it.
The core point of this branch is that other members of the team can continue to develop based on the development branch, and the members responsible for repairing can quickly repair the production environment problems independently.
Create repair branch
The repair branch is created in the master branch. For example, version 1.2 is the currently running version of the production environment and fails due to a defect. But the code on the development branch is not stable. We need to create a repair branch and start fixing the problem:
$ git checkout -b hotfix-1.2.1 master Switched to a new branch "hotfix-1.2.1" $ ./bump-version.sh 1.2.1 Files modified successfully, version bumped to 1.2.1. $ git commit -a -m "Bumped version number to 1.2.1" [hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1 1 files changed, 1 insertions(+), 1 deletions(-)
Don’t forget to switch the version number in the code after switching the new release version
Then fix the problem in one or more committed code.
$ git commit -m "Fixed severe production problem" [hotfix-1.2.1 abbe5d6] Fixed severe production problem 5 files changed, 32 insertions(+), 17 deletions(-)
Close repair branch
After the repair is completed, the repair branch needs to merge the main branch, and also need to merge back to the development branch, so as to ensure that the repair is included in the next release code. This is exactly the same as closing a publish branch.
First, update the label of the master code and publish:
$ git checkout master Switched to branch 'master' $ git merge --no-ff hotfix-1.2.1 Merge made by recursive. (Summary of changes) $ git tag -a 1.2.1
Then merge the code back into the development branch:
$ git checkout develop Switched to branch 'develop' $ git merge --no-ff hotfix-1.2.1 Merge made by recursive. (Summary of changes)
A special point here is that if there is a release branch at this time, the changes of the repair branch need to be merged into the release branch instead of the development branch. The repair can be brought back to the development branch through the publishing branch（ If the development branch also needs to fix the problem immediately, it can’t wait until the publishing branch merges back. You can also merge the change safely to publish the branch first.)
$ git branch -d hotfix-1.2.1 Deleted branch hotfix-1.2.1 (was abbe5d6).