📜 ⬆️ ⬇️

Gitlab flow

This is a translation of a fairly important article about GitLab Flow, an alternative to Git flow and GitHub flow. The article was written in 2014, so the screenshots have become outdated. Nevertheless, the article itself is more than relevant:




Branching and merging branches in git is much simpler than in earlier version control systems, such as SVN. Therefore, there are many ways to organize team work on code, and most of them are good enough. At the very least, they offer many advantages over what happened before git. But git itself is not a silver bullet, and in many teams the organization of the workflow with git has a number of problems:



We want to introduce you to GitLab flow - a well-defined set of practices that solves these problems. It integrates into one system:




This article describes all aspects of GitLab flow, including branching, task integration, continuous integration, and deployment. Its goal is to help new teams switch to git and immediately implement simple, transparent and effective rules for working with it.


Four stages (working copy, index, local repo, remote repo) and


In most version control systems, in order to share code with colleagues, you need to do one action - commit to the repository. In git, the same thing happens in three steps:


  1. Add changes from the project workspace to the index (prepared files area, staging area);
  2. Make a commit based on the index;
  3. Push commit to remote repository.

Mastering these actions is the first step in learning git. Next is the work with the branches.


Multiple long running branches and merging in all directions


If you do not set any rules for working with branches, the entropy begins to grow in the repository:



To solve these problems, a standard work model is usually implemented, for example, git flow or GitHub flow . We believe that all these models have the potential for improvement, so we developed the GitLab flow.


Git flow and its limitations


Git Flow timeline by Vincent Driessen, used with permission


The Git flow workflow model was one of the first to emerge and became quite widely known. It assumes the presence of a master branch, a branch for accumulated changes of develop , as well as separate branches for features, releases, and hotfixes. Developed changes are merging into develop , from there to release branches, and as a result get into master . Git flow is quite detailed and clearly defines the workflow, but its complexity creates two problems.


First, developers should use the develop , not master branch, because the latter is reserved for release code. This contradicts the usual practice of calling master main branch, from which other branches branch off, and into which the result is merged. Often, developers mistakenly make some changes only in the master , forgetting to develop . And the majority of graphical interfaces to git, by default, consider the master branch as the main branch, so they have to switch or configure something every time.


Secondly, the extra complexity arises because of the release branches and hotfixes. Most teams, especially small ones, can easily do without them. Today, most organizations adhere to the practice of continuous delivery (continuous delivery), which assumes that the code from the main branch can be deployed to production.


Therefore, you can exclude branches of releases and hotfixes and all the extra work that is required for them. An example of such extra work is the reverse merge of the release branches in master . To solve this problem, there are special tools, but they also require the study of documentation and only add complexity.


GitHub flow is a simpler option.


Master branch with feature branches merged in


In contrast to the complex git flow model, the GitHub flow model was developed. It has only master and feature branches. This simplification led to the successful implementation of GitHub flow by many companies. Atlassian has proposed a similar strategy . But, unlike GitHub, they prefer to do a rebase (not a merge of the branches in the master .


The merge of all changes to the master and the frequent deployment make it possible not to write code “on the table”, but to immediately release the changes. This is in line with the ideas of lean manufacturing and continuous delivery. But a lot of questions remain unanswered: when exactly to deploy and in what environments, how to release releases, how to connect all this with the task tracker. GitLab flow answers all these questions.


GitLab flow: production branch


Master branch and production branch


GitHub flow is built on the assumption that you can deploy your code to production at any time, immediately after the merge of the feature branch in the master . This is true for SaaS applications, but is incorrect in many other cases. It happens that you can not affect the exact time of release. For example, you release an application for iOS and each update must be validated in the AppStore. Another example is when you can release at a specific time (for example, from 10 to 16 on weekdays, when all employees are at work), but you can take a branch to master at any time.


To control the release of code in production, GitLab flow suggests using a special branch, production . Configure automatic deployment of code from this branch with each change in it. Now for release it is enough to make merge from the master branch in production . The status of the branch will give you exact information about which version of the code is now released, and the approximate release time can be determined by the time of the creation of the merge commit. If you need absolute accuracy, you can create a new tag with the timestamp in the description during the deployment process.


GitLab flow: branches for several environments


Multiple branches with the code cascading from one to another


It may be useful to have a separate environment (environment) in which the deployment from the master branch occurs. In this unique case, the name of the medium may differ from the name of the branch.


Suppose you have several environments: staging, pre-production, and production. The code from master automatically deployed to styling. As soon as you are ready to deploy it to pre-production, you create a merge request from master to pre-production . Accordingly, merge from pre-production to production means final release. Such a process, when all commits pass through branches in a strictly defined order, ensures that the changes have been tested in all environments.


If you need to quickly “push” a hotfix to the production, you can implement it in the usual feature-branch, and then open the merge-request to master without deleting the branch. Now, if the code in the master passes the tests and is viable (correctly configured continuous delivery should guarantee this), you can hold the hotfix branch consistently in pre-production and production . If the changes require additional testing, then instead of an immediate merge, you need to open merge-requests in the same branches. In the “extreme” case, a separate environment can be created for each branch. This is done, for example, in Teatro .


GitLab flow: release branches


Master-picks from master


You will need release branches only if you release software for external clients. In this case, each minor version will be stored in a separate branch ( 2.3-stable , 2.4-stable , etc.).


Stable (stable) branches should be created from the master branch. They need to be created as late as possible to minimize the addition of hotfixes to several branches. After the release branch is created, you can only include fixes for serious bugs. Follow the "upstream first" rule: whenever possible, first make merge corrections to the master , and only from there - cherry-pick to the release branch. Thanks to this rule, you will not forget to make cherry-pick patches in master and will not encounter the same bug in the next release. The "upstream first" rule applies including in Google and Red Hat . Every time a bug fix is ​​added to the release branch, you need to increase the third number in the version number (according to the rules of semantic versioning ). Mark this version with a new git tag. Some projects use the stable branch, which always points to the same commit as the last release. The production branch (or master in git flow rules) is not needed in this case.


GitLab flow: merge / pull requests


Merge request with line comments


Merge-request or pull-request is created in the git-repository management system. This is a request for merzh one branch to another, like a task assigned to any performer. GitHub and Bitbucket use the term “pull-requote”, because the first necessary action is to make a pull of the proposed branch. GitLab and Gitorious use the term "merzh-request", because the final action is, in fact, merge branches. Later in this article we will call this a merge request.


If you are working on a branch for more than a couple of hours, it makes sense to share the intermediate result with your colleagues through a merge-request. Do not assign it to anyone, but just mention (with the /cc @ command) your colleagues in the request description or in the comment - they will receive a notification. This will mean that the request is not ready for merge, but it is already possible to give feedback on it. You can explicitly indicate that the work on the request is not completed. To do this, start the request header with [WIP] or WIP: that is, "Work in progress". Such a merge-request can not even be locked up via the GitLab interface (although you can still manually use git).


The GitLab interface allows you to leave comments both to the request as a whole and to specific lines of code. Thus, the Merge-Request already includes tools for reviewing the code, and you will not need any additional tools. According to the results of the review, anyone can make edits with the following commit to the same branch (usually the author of the request makes it). All subsequent commits started in the same branch are included in the merge-request, and the diff is updated automatically and works correctly even with push -f .


When the feature is ready, and the branch can be merged, assign a request to someone who knows the project code well (and who has rights to the merge in the master ). This person is responsible for the final review and decides whether to hold the result or close the request without merge.


GitLab has a standard practice - to “protect” long-lived branches (such as master or production ). Branch protection does not allow members with a Developer access level to push any changes into it .


Therefore, for a merge to a protected branch, you need to open a merge-request assigned to a participant with a higher level of access.


GitLab flow: integration with tasks (issues)


Merge request with the branch name 15-require-a-password-to-change-it and assignee field shown


GitLab flow allows you to explicitly link code and tasks from the tracker.


Any significant changes in the code must be accompanied by a task in which the requirements and the meaning of the changes are formulated. It helps to stay within the task, and also gives the team an idea of ​​what you are doing. In GitLab, every change in the code base begins after the task is created in the tracker. If the intended changes are at least somewhat serious (for example, they require more than an hour of work), then the work must begin with the formulation of the task. Many teams already follow this rule, because they always estimate the time to complete a task before taking it to the sprint.


Task headers should be formulated to describe the desired state of the system.


A good example: "As an administrator, I want to be able to delete a user without errors."
A bad example: "Admin can not delete users."


Starting work on the task, create a new branch from the master branch. Its name must begin with a ticket number, for example 42-admin-can-remove-users .


When you have completed the task or want to receive an intermediate feedback, open the merge-request. Remember to be able to send an alert ( /cc @ ) to colleagues and mark WIP:


At the moment when you consider that the work is completed, assign a request to the reviewer and remove the WIP:


The reviewer can accept (detain) the request both via the command line and through the button in the request interface. Clicking on the button automatically creates a merge commit, the description of which is formed on the basis of the request description. A merge commit is useful in that it saves the time and circumstances of merge in history. Therefore, by default, a commit is always created, even if a "fast-forward merge" was possible, when the master simply switches to the last commit of your branch. In git, this strategy is called "no fast-forward" and is used with the git merge --no-ff command. GitLab EE and .com offer a choice of behavior for Merzh, details later in the article.


The feature branch is usually no longer needed after merge, so the request interface allows you to delete it. Suppose that the branch was frozen, after which you discovered some flaws and rediscovered the task. If the old branch is deleted, you can create a new branch with the same name and continue development in it. As a rule, one task corresponds to no more than one branch, but several tasks can be solved in one branch.


Binding tasks and merge-requests


Merge request


In a commit message, or in the description of a merge request, you can mention the task by its number, using a trigger word, for example: fixes #14 , closes #67 . In this case, GitLab publishes a comment in the mentioned task with a reverse link to the commit or request. And in the merge-request a list of related tasks appears. When you take the code to the main branch, the associated tasks will be marked as completed. Please note: triggers are recognized only in English, that is, fixes #14 will work, and fixes #14 will not.


If you want to create a link to the task, but do not close it, just write its number: "Duck typing is preferred. # 12".


If a task covers several repositories, it is best to create the main task in one repository and link separate tasks to it in other repositories.


Rebase and commit committing


Vim screen showing the rebase view


Git allows you to merge (squash) several commits into one or change their order using the rebase -i command. In GitLab EE and .com, you can do this directly before merge through the web interface. It makes sense if you made several small commits in the process of work, but you want to get one into master , or if you want to build commits in a logical order.


Remember that commits that are already in the remote repository and, moreover, in a stable branch, cannot be re-booted. The reason for this is that something could leave a link to them or pull (cherry-pick) into its branch. Rebeyz changes identifiers (SHA-1) commits, because it actually creates new commits from them. As a result, your changes appear in git history with several different identifiers, which leads to confusion and errors. Rebeyz also makes it difficult to review the code, because information is lost about what changes were made after the review. If commits of different authors are combined, then the information about authorship will also be lost. This deprives the authors of an indication of their authorship, but also hinders the work of git blame (it shows in which commit and by whom each row was changed).


Regularly doing commits and pushing them to a remote repository is a good practice that allows colleagues to see what you are working on. But with this approach, one task is spread over many commits, so the development history becomes quite difficult to view. These small commits could be merged into one, but this will lead to the loss of identifiers. Instead, you can view the history on merge commits: they always explain the essence of the changes and indicate the moment of the merge of the whole branch.


Changes that have already entered the master cannot be erased from the history and it is not so easy to undo with git revert . If all the commits were merged into one with a rebase , you can revert to that single commit. However, we are convinced that merging commits does more harm than good. Fortunately, git can cancel merge commits . If you change your mind and want to return the canceled merge commit, then apply revert to the commit created as a result of the first revert . Git will not let you commit the same commit twice anyway.


To make this possible, you must first create this merge commit. Therefore, if you manually add the option --no-ff . The repository management system will do it for you at the time of the Merge-Requests.


Do not change the order of commits using rebase


List of sequential merge commits


Git allows you to rebuy feature-branches to master , as a result of which this branch’s commits appear in the history after commits to master . This allows you to make merge without merge commit and as a result you get a simple linear history. But the same rule applies here as with the merging of commits: don’t touch what has already got into the remote repository. We recommend that you do not even re-intermediate the interim results of your work, which were submitted for review via merge-requisition.


Using rebase causes you to repeatedly resolve the same conflicts . In some cases, this can be done with the git rerere (reuse recorded resolutions). But it is even easier - not to re-raise at all and to resolve conflicts only once, with merge. The less you encounter any merger conflicts, the better.


In order to avoid unnecessary conflicts, you should not overload the master in the feature branch too often. Let's look at the three possible causes of master merge elsewhere: “code pulling” (leveraging code), merge conflicts, and long-lived branches.


If you need to “pull up” changes from the master to the feature-branch, you can usually get away with pulling (cherry-pick) of one desired commit.


A conflict with a feature-merge merge is usually resolved by creating a merge commit. If the lines of your file can be in random order, then some conflicts can be avoided by setting gitattributes . For example, in the .gitattributes file of the .gitattributes repository there is the line CHANGELOG merge=union , and this allows you to merge changes automatically.


The last situation when it is necessary to master somewhere else is the use of long-lived branches, which periodically need to be updated to the current state. Martin Fowler, in his article on feature-branches, discusses the practice of continuous integration (CI). We in GitLab confuse CI with testing branches a bit.


To quote Fowler: “I know people who claim to practice CI because they build every branch and every commit and can even use a CI server. What they do is called continuous building. it is also a noble cause, but there is no integration, which means that there is no “continuous integration”. "


The solution is that feature branches should exist for a short time and quickly merge. You can focus on the period of one working day. If the developer keeps the branch for the implementation of the task for more than one day, think about splitting the task into smaller parts. Alternatively, feature toggles can be used.


There are two strategies for working with long-lived branches:



GitLab EE offers the opportunity to rebase immediately before accepting a merge-request. , Merge Requests Rebase .


Merge request settings


- rebase before merge .


Merge request widget


GitLab rebase . rebase , .


: -, . , . . , — . , , , .


-


Emoji bar in GitLab


— +1 -1.
GitLab , , , « » -.



Remove checkbox for branch in merge requests


, . , - . , — . , .


master , . GitLab . , , , . . , -.



Good and bad commit message


. , , . , , . SVN, , . , /-, .


, — . , .


: « , ».


, : «», «», «» .. «», «» , "fix" ( ) . , Tim Pope .



Merge requests showing the test states, red, yellow and green


(CI server), , master . , master . GitLab flow master , «». - , . CI, GitLab CI Travis, (build) -.


, , . , . , , master . , master , , , .


, , . - , master feature- (.. ), CI . feature- , , .



Shell output showing git pull output


, feature- master . , . , -. , master . feature-, . feature-, .


Links



nick_volynkin « », http://nadmosq.ru


')

Source: https://habr.com/ru/post/316686/


All Articles