We take code quality seriously for two reasons: 1) we care about the products we develop, and 2) we don't want to waste our client’s time and money on unnecessary software maintenance and modifications.
We use a variety of techniques and tools to control code quality. One of these tools is GitHub. We regularly use GitHub for deploying our software. Its simple yet effective branching strategy helps us manage, support, and track all the code we write at RubyGarage. In this article we’ll describe the full cycle of work with GitHub from the start of a project to its production release.
1. Сreate a New Project
As with other version control systems, in Git projects are kept in repositories. The first thing you need to do to create a new repository is give it a name. The name of your repository should be short and memorable, so everybody involved in the project can easily find it. We named our repository “rubygarage-gitflow.”
Next, we have to push our project to GitHub and create a master branch. We need to run the following commands to create a git file for our application:
Now we have to enter the directory where the folder with our project will be stored and initialize the project. If this project already exists on GitHub, we can run the command
to copy it to our local system. If the project doesn’t exist yet, then an empty folder with the name “rubygarage-gitflow” will be created at the directory we specified.
2. Create a Development Branch
To create a development branch we have to run the command
where -b creates a new development branch.
If the development branch already exists locally, we can just use the
command. To see the list of all local branches on our computer we can run
And if we need to delete a local branch from our computer, we can easily do it with
2.1 Create a Feature Branch
Now that we’ve created the development branch, we’ll create a feature branch and name it (feature/<feature name>). To create this branch we have to run the command
This feature branch splits off from the development branch. We can split off several feature branches at the same time.
For example: If we run
from the feature/<feature name> branch, our feature branch will be split off from the feature/<feature name> branch, not from the development or master branch. We can do this in case our current feature branch isn’t merged to the development (it’s on the stage of code review). But we need this feature to develop the next one.
Branch names contain two components to clearly show what’s in the branch – feature/<feature name> for new functionality, bugfix/<bugfix name> for bug fixes, hotfix/<hotfix name> for hotfixes, and so on.
2.2. Commit Changes
Once we’ve made changes to a branch, we need to commit those changes to save them to our repository. Committing changes adds them to the branch. To commit changes we run
Then we type
We could also use
This command will save all changes to the existing commit, but that’s not a very good practice and we avoid doing this in most situations.
2.3 Push the Project
Pushing the project means sending changes to the remote GitHub server. All changes on our local computer are synchronized with the remote server to let other developers see the changes in the branch. To push the project to GitHub we use the command
But if we’ve committed changes with --amend we need to push the project with force by running the command
To push with force -f is dangerous because if other developers have made any changes to the branch that don’t exist on your local server (but are saved to the remote GitHub server), pushing with force will completely overwrite the server branch with your local branch (where only your changes are saved). In other words, you risk erasing newly written code.
After we’ve pushed our project to the remote GitHub server, the next step is to add all committed changes to the development branch.
2.4 Create a Pull Request
A pull request is like a message to the owner of the repository. You create a pull request when you notice problems or just want to make some adjustments to the already written code. One pull request should correspond to one bug or one feature. Don’t overload your pull requests.
2.5. Code Review
As soon as we’ve added a pull request, we have to get it approved by the whole team who’s working on the project. They have to review the committed changes and leave comments about anything that needs to be fixed.
Once changes are approved by the team, we can merge them into the development branch. It often happens that the development branch includes code not present in our local repository. This can cause conflicts between the branches. To resolve these conflicts we have to move the newest changes from the remote development branch to our local branch by running the command
This command will completely update our local development branch.
Now we need to merge our new development with our feature branch – for example, feature/something-cool. This is called rebasing. To do a rebase we enter our branch
and then run the command
If there aren’t any conflicts, we’re good to go, but if there are conflicts, then the process of rebasing will stop and show us in which file a conflict occurred. For example, we might see that a conflict was found in the file .../app/models/order.rb. This is a hash of the conflict commit:
After we’ve manually resolved the problem, we can continue rebasing by entering
We’ll continue this process until all issues are resolved and the rebasing is complete. After rebasing, we can run the command
and voilà – we can merge!
During code review, everybody who takes part is assigned to a pull request. We can tag pull requests with labels such as “work in progress” (if, after code review, a developer will be making fixes). The process of code review looks like this:
After code review we merge this feature branch with the development branch.
3. Merge to Master Branch
4. Merge to Production Branch
Our branching GitHub Flow is designed in the following way:
If you don’t want to use GitHub for some reason, there are alternatives such as GitLab and BitBucket. The general principles we just described apply to all popular version control systems. Working with a version control system such as GitHub helps to maintain high quality code.