11 KiB
| layout | author | title | lang | lang-ref |
|---|---|---|---|---|
| post | Luan Luiz Gonçalves | Development flow with the GitFlow model | en | Development-flow-with-the-GitFlow-model |
GitFlow
GitFlow is a branch model for software development, using the git version control tool. This model, created by software engineer Vincent Driessen, became popular. According to * Driessen *, suitable for software with explicit versioning or to maintain multiple software versions, ensuring stability of the main branch during the development process.
{% include image.html url="/assets/posts_imgs/gitflow.png" description="Figura 1: Fluxo de desenvolvimento do modelo de ramificação GitFlow." width="80%" height="80%" align_class="aligncenter" %}
The model has an organization of branches and workflow that makes it easy to find points of code changes, easily visualizing each implementation.
Repositórios remotos
The project repository is centralized. Each developer contains a fork from the central repository to push the changes / commits instead of directly manipulating the central repository. Thus, for changes to be added to the central repository, the developer must create a Pull Request, allowing project administrators to review the changes before accepting them. Pull can also be made between forks, creating sub-teams to work on the same implementation - sub-teams of two or more members. The following image shows this configuration of remote repositories:
{% include image.html url="/assets/posts_imgs/centr-decentr.png" description="Figura 2: Configuração de repositórios: Centralizado mas descentralizado." width="60%" height="60%" align_class="aligncenter" %}
In the previous image, origin refers to the central repository and the other repositories are the central forks - Alice, Bob, David and Chair. The image illustrates the Alice / Bob, Alice / David and Clair / David sub-teams. It is worth mentioning that there is no Pull Request made to the central repository for changes in work in progress, the developer or a sub-team must finish the work in their respective fork before making the Pull Request.
Branches
In the GitFlow model, the central repository of the project contains two branches: * master * and * develop *, both with infinite life. The master is the main branch and its source code (HEAD) is always a stable version - production release. The develop branch always contains full feature implementations for the next release.
Developers do not work directly on the master and develop branches. Supporting branches are created for implementing bug fixes, implementing features, changing release metadata and other release processes. Unlike master and develop, support branches are finite and have implementations in progress.
Types of support branches:
- Feature: for implementing new features;
- Release: for release processes like metadata changes and software packaging;
- Hotfix: for bug fixes that can't wait for the next release.
Each of the types, in addition to having a specific purpose, are subject to strict rules about which branches may be their source branch and which branches should be their merging destinations, being categorized by the form of use. Next, we will see the details of each of the types of support branches, in parallel with examples illustrating the workflow of the GitFlow model and the commands used in each step!
Branches feature
{% include image.html url="/assets/posts_imgs/feature-branchs.png" width="18%" height="18%" align_class="alignright" description= "Figura 3: Branch feature." %}
Rules:
- Branching from the develop branch;
- After finalizing the implementation, they are merged into the develop branch;
- There is no name convention, the name only refers to the feature under development;
- They exist only in the forks of the central repository.
Creating a branch feature
To implement a new feature, a support branch of the feature type is created from the develop branch. Example:
$ git checkout -b myfeature develop Switched to a new branch "myfeature"
The command git checkout with the parameter-b <branch name>, creates the branch and changes to the created branch. The develop parameter, at the end of the command, informs you that the branch will be created from the develop branch.
Merge the branch feature into the develop branch
After completing the implementation of the feature in the myfeature branch, the branch is merged into the develop branch. Once the merge is done, we delete the myfeature branch and upload the changes (push) to the developer's remote repository. For this, we use the following commands:
$ 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
In this and the following example, the origin parameter is the link to the developer's remote repository.
The --no-ff flag causes the merge to always create a commit to record the historical existence of a branch, grouping the commits of the branch. Compare, in Figure 4, the merge command with and without the flag:
{% include image.html url="/assets/posts_imgs/merge-flags.png" width="65%" height="65%" align_class="aligncenter" description="Figura 4: Diferença entre o merge com e sem a flag –no-ff." %}
If we don't use the flag, we would have to read the commits' log messages to identify which commits are consolidating an implementation together. With the flag, this identification becomes much easier. Figure 4 highlights the commits that consolidate the implementation of a feature, in both situations.
Branches release
Rules:
- Branching from the develop branch;
- After finalizing the implementation, they are merged into the develop and master branches;
- Naming convention:
release- <version number>.
In the branch release, we finish the software release. The metadata is changed, updating the version number of the software and performing other release procedures such as packaging the software. In addition, minor bug fixes are allowed. The branch is created when the implementations in the develop branch are in a state very close to the new software release.
Finishing the release process, the release branch is merged for the develop branch and the for the master branch. At this point, the develop branch is free to implement new features in a future release.
Creating the branch release
In this example, number 1.2 is the release version. Note that the branch name follows the release- <version number> convention:
$ 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 the branch and switching to it, we carry out the release procedures. The bump-version.sh file is a fictional script that changes the metadata files to reflect the new version. After executing the script, we commit to record the changes.
Finalizing the branch release
When the state of the release branch is ready to become a real release, some actions need to be taken. First, the release branch is merged into the master (since every commit on the master is a new release by definition, remember). Then, we assign a tag to this commit on the master, to have a reference to this historical version. Finally, changes made to the version branch need to be merged back into the develop branch, so that future versions will also contain those changes.
The first two steps in Git:
$ 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
Merging the branch release into the develop branch:
$ git checkout develop Switched to branch 'develop' $ git merge --no-ff release-1.2 Merge made by recursive. (Summary of changes)
This step can lead to a merge conflict. If so, correct and confirm.
Now, the release process has been completed and the release branch can be removed, as we no longer need it:
$ git branch -d release-1.2 Deleted branch release-1.2 (was ff452fe).
Branches hotfix
{% include image.html url="/assets/posts_imgs/hotfix-branchs.png" width="40%" height="40%" align_class="alignright" description="Figura 5: Branch hotfix." %}
Rules:
- Branching from the master branch;
- After finalizing the implementation, they are merged into the master branch;
- Naming convention:
hotfix- <version number>.
Hotfix branches are very similar to release branches, as they also deliver a new version of the software, although not planned. They arise from the need to act immediately in an unwanted state from a released production version - production version.
When there is a critical error in a production version, we cannot wait for the next release to fix it. If so, a hotfix branch is created for the fix. The essence is that the work of team members (in the develop branch) can continue as long as the correction is made.
Creating the hotfix branch
This branch is created from the master and its name follows the hotfix- <version number> convention. In the following example, the bug is in version 1.2 (1.2.0) and we have added the third version number. This increment follows the rules of [Semantic Versioning 2.0.0] (https://semver.org/):
$ 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(-)
After creating the branch and increasing the version number in the metadata files, we can fix the bug in one or more commits:
$ git commit -m "Fixed severe production problem" [hotfix-1.2.1 abbe5d6] Fixed severe production problem 5 files changed, 32 insertions(+), 17 deletions(-)
Terminating the hotfix branch
Upon completion of the bug fix implementation, the hotfix branch is merged with the master and develop branches. First, update the master and tag the version with the tag:
$ 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 include the bug fix in develop as well:
$ git checkout develop Switched to branch 'develop' $ git merge --no-ff hotfix-1.2.1 Merge made by recursive. (Summary of changes)
Finally, remove the hotfix branch:
$ git branch -d hotfix-1.2.1 Deleted branch hotfix-1.2.1 (was abbe5d6).