JoBins採用企業サイト JoBinsエージェントサイト

アカウントをお持ちの方はこちら 採用企業ログイン
エージェントログイン


background

Understanding Git and following Gitflow Branching Model

Sep 26, 2018

Git is the backbone for code collaboration in a multiple team member. Git branching and merging can also be tied to an issue flow if you follow a proper branch naming convention.

Source code Version Control System (VCS) and automated testing open doors to other great software quality and delivery practices like continuous integration and automated deployment etc. Git is a distributed system that is very popular and easy to use once you get used to it.

All team members pushing code to the main branch (master/develop) is not a good practice. To get the most out of git, it is a good idea to do feature branching and follow a branching model. GitFlow is one of the options for doing a feature branching model, In this article, I would briefly elaborate on how a team can use gitflow and get the most out of using git.

Gitflow Diagram

The gitflow has two main branches master and develop (parallel to master) with an infinite lifetime. We consider master to be the main branch which reflects production-ready state and develop branch which reflects a state with the latest delivered development changes for the next release. Our development model uses a feature, release, and hotfix as supporting branches (has a limited lifetime) next to the main branches to aid parallel development between team members.

Feature Branches

Release Branches

Hotfix Branches

May branch off from: develop

May branch off from: develop

May branch off from: master

Must merge back into: develop

Must merge back into: develop and master

Must merge back into: develop and master

Branch naming convention: feature/{jira_module_name}/{jira_ticket_id}/*

anything except master, develop, release/*, or hotfix/*

Branch naming convention:

release-*

Branch naming convention:

hotfix/{jira_module_name}/{jira_ticket_id}/*

If a new bug fix or feature needs to be done, the developer will follow the given steps:

1) Create a feature branch from latest develop branch following a naming convention like feature/agent/123 for feature with agent module and Jira ticket 123

2) Work on it, after completing it push the branch feature/agent/123 to the remote git repository (could be bitbucket or any other), preferably with just one commit

3) Open a pull request (or merge request) from the pushed branch feature/agent/123 to develop

4) After the pull request is accepted, deploy it on QA or staging environment and test it.

5) After repeating the above steps and reflecting the desired state of the new release, release branches are created from the develop branch. At least all features that are targeted for the release to be built must be merged into develop branch at this point in time.

$ git checkout -b release-1.1 develop
Switched to a new branch "release-1.1"
$ ./bump-version.sh 1.1
Files modified successfully, version bumped to 1.1.
$ git commit -a -m "Bumped version number to 1.1"
[release-1.1 74d9424] Bumped version number to 1.1
1 files changed, 1 insertions(+), 1 deletions(-)

6) Then release branch is merged into master (since every commit on master is a new release by definition, remember). Next, that commit on master must be tagged for easy future reference to this historical version. Finally, the changes made on the release branch need to be merged back into the develop branch, so that future releases also contain these bug fixes.

7) After creating a tag from the release branch deploy it to production

8) Properly test it on a production server, if everything is fine on production after testing finally merge the tag to master.

The above steps are repeated for each feature or bug fix. Generally, it’s good to wait an hour or two to merge the tag to master to make sure at that all the things are running fine.

Handling Git Conflicts

There might be merge conflicts while merging branches to the main branch which has become a pain for every team members. I am going to reveal 4 simple tricks to avoid git conflicts.

Trick #1:  Keep your changes small

Many big merge conflicts are results of long-living branches. If you work in your own branch for several days or even weeks, the risk is high that someone else changes parts of the code you have touched in another branch. That would lead to merge conflicts. On the other hand, if you have a short-living branch, meaning it is merged back into the develop or master branch after a few hours, there will probably be no merge conflict. Even if there is a conflict, it can usually be resolved very quickly because there is much less code to think about. As a side effect, it will make deploying and testing changes easy too.

Short Living Branch    

Trick #2: Small Modules

The Single Responsibility Principle (which is part of the SOLID principles of software design) says that “a class should have one, and only one, a reason to change“. If we take this approach seriously, there should never be a situation in which two developers change the same code at the same time because that would mean they are working on the same task. You see, a modular architecture and small classes do not only help to increase the quality of the code design but also decrease the chance to merge conflicts.

Trick #3: Rebase with your main branch (generally master/develop) when it changes

When your main branch changes, rebase the branch you are working on with it. Usually, master/develop is the main branch so it will be best if you rebase with the master at least once a day. This saves you from bringing in lots of changes done by another team member late. It’s the same concept as above, get small changes step by step many times than getting it all at once. At the end of the day always do the following, given you are on your working branch

 git checkout master/develop 
git fetch 
git pull — rebase origin master/develop 
git checkout -
git rebase master

You get the latest master. Then you go back to your previous branch and rebase your branch with the latest master.

Trick #4: Review pull requests faster and merge them into the main branch

An open pull request for a long time will invite code conflicts soo. Have a rule, pull requests need action by 3 days of opening them. You can review code, if the code is ok deploy and merge or review code, fix issues then deploy and merge. This will help the team ship things faster as well as not have pull requests open unattended for weeks.

Useful Tip

You followed the above rules, still landed in a git conflict situation? Use git cherry-pick. If you have more than one commit in your working branch first squash it to one commit. Then create a new branch out of master/develop branch (your main branch) and do git cherry-pick.
 Given you have only 1 commit on your working branch feature11 and you are on feature11 right now, do the following:

 git checkout master/develop
git fetch
git pull — rebase origin master/develop 
git checkout -b feature/agent/JB-21/feature1
git cherry-pick 249bd9b150fdb1e6fc9e58af9823f70cc52579a3

In the above example 249bd9b150fdb1e6fc9e58af9823f70cc52579a3 is used for demo only. You can know your SHA hash with git log -1 being on branch feature/agent/JB-21/feature1

Bonus Tips

Stashing your work

 cd my-project
git checkout -b feature-a

# working on feature-a, some files changed say 3 of them
# bug-x discovered, need to fix it urgently so let's stash changes
# (save them for later)
git stash save feature-a

# lets go to master and create a new branch to fix bug-x
git checkout master
git checkout -b bug-x

# work to fix bug x for 1 hr, its fixed now.
git add .
git commit -m 'bug-x fixed with change in config files'
git push origin bug-x

# then open a pull request on github for bug-x,
# and come back to working on feature-a
git checkout feature-a
git stash pop

Squashing your commit

You did this big feature taking 4 days’ work and as a good git user, you did commits when the code was stable. So now you have 10 commits in total for the feature-b you worked in for 4 days. Do you really want to send a Pull Request with 10 commits, maybe along the way you wrote some commits messages that are not so relevant now. So how do you get the 4 commits to becoming 1, it's easy you squash your commits using git rebase -i, how?

you need to execute the following command:

 git rebase -i HEAD~4 

#the last number, here 4 is the no. of commits you want to squash.

# you will get a screen like this :

pick 8dd81e6 feature-b changes to the config files
pick 7ea892d Feature-a fixed class A b and C
pick a465749 Feature-b fixed tests
pick cd6f406 Feature-b fixed tests

# change all picks except of the first one to s.
# s is short for squash like below:
pick 8dd81e6 feature-b changes to the config files
s 7ea892d Feature-a fixed class A b and C
s a465749 Feature-b fixed tests
s cd6f406 Feature-b fixed tests

# now exit your editor, if you are using vim :wq
# then as you are squashing commits you can select which commit messages to pick
# from a screen like:
# This is a combination of 4 commits.
# The first commit's message is:
feature-b changes to the config files

# This is the 2nd commit message:

Feature-a fixed class A b and C

- [x] Works for A and B

# This is the 3rd commit message:

Feature-b fixed tests

* fixed most test

# This is the 4th commit message:

Feature-b fixed tests

- [x] fixed all tests

# Pick the ones that you need or delete, for this example I will not delete anything
# and quit the editor

# 4 of your commits are squashed into 1.

Conclusion

I believe you have learned something new and will be willing to integrate the gitflow in your daily work with your team decreasing complexity and increasing productivity.

There is no any silver bullet to avoid git conflicts all the time. You will face it now and then. If you run into git conflicts every day the process and system need to change. Be logical, if you have a pull request with 50 files changed and 500 new lines you will face conflicts.

I hope you face fewer git conflicts or even completely avoid them.

For a detailed example and git commands read the following slides:

http://prezi.com/yhiyokafkimb/?utm_campaign=share&utm_medium=copy

For learning git branching in detail:

https://learngitbranching.js.org/