In software development, version control is absolutely critical. Without a solid version control system, you’re just undermining all the hard work that goes into any development project.

At XSolve, we’ve been using Git for version control for several years now.

Having tested it in a variety of scenarios, including back-end and mobile apps, and thanks to our close collaboration with clients, we’ve developed our own best practice ways of working with Git.

In this post, we’ll show you the standard Git-Flows we’ve created and now use as standard.

Best practice

On the internet, you can find various methods of working with Git. In most of them, there are three basic branches containing particular code versions:

  • master branch: including stable branches or, depending on the contract with the client, branches published for acceptance tests;
  • develop branch: this might also be called the integration branch; new and completed functionalities created during sprints are added here;
  • feature branch: including the code for new functionalities or those that are still being built; this sometimes also includes completed functionalities which have not yet been assigned to an edition.

Below, you can see one of the most popular Git-Flows (this is actually our sample working method)

git flow best practice


Git is not everything

Of course, working with Git is not enough. The process must result in code of the highest quality, with the developed functionality fully meeting the restrictive requirements. We use the following six criteria for quality:

Clean Code

The code which is built during the creation of a new functionality is actually delivered based on the principles described in Robert C. Martin’s book. Additionally, for each technology, we’ve developed our own extensions which are based on Clean Code and SOLID principles, etc. What’s more, we’ve got our own internal wiki, where all JAVA, PHP, or mobile teams note down their own Clean Code practices developed over the years.

Definition of Done

All developer teams have their own Definition of Done (or DoD), which decides whether a newly created functionality has been built the right way or not. Of course, depending on the nature of the project, these definitions may differ. For example, it’s obvious that Android or iOS apps which do not connect to the internet will not need server deployment but rather testing on selected mobile phones. In some projects, acceptance tests on the part of the client are an important aspect, as well as fulfilling the conditions of code quality metrics, e.g. the minimum percentage of particular test coverage for the whole application.

Code Review

Every functionality completed by a developer must be reviewed and evaluated by other developers. No code change can be introduced without being verified by another developer.

Manual test

Each functionality has to be tested by a tester.

Automated tests

Practically every app created at XSolve contains automated tests. They frequently identify errors which cannot be detected during manual tests. The project and the client themselves determine how many automated tests need to be implemented.

Integration tests

Every project which communicates with external systems needs integration testing. Various teams, depending on the technology, use software to simulate external systems.

How it looks in theory

In the Java team, we’ve developed our versions of the three branch types:

  • master – containing the app version which is presented to the client and then uploaded to the production server;
  • develop – the branch containing new functionalities which have not been uploaded to the production server;
  • feature branch – in Java, we don’t use the feature or hotfix prefixes, instead we name this branch after the JIRA task, e.g. iso23; each feature branch is merged to the develop branch.

All versions of the application are tagged with a unique version number once they have been uploaded to the production server.

Git flow best practice - verisons tagged unique number


Syncing branches

Some tasks are highly complicated, requiring several people to work on them at the same time. Let’s imagine we have to create a big indivisible functionality. Adam takes care of the database, Peter takes the server, and Anna is in charge of the front-end. The whole is treated as one large story. In this situation, we create a new branch which we call a sync branch. Out of this branch, Adam, Peter, and Anna will build their own small branches and they will add their changes to it. After completing the whole work, everything is added to the main develop branch. Before that happens, though, the develop branch code must be accepted by the sync code. If any conflict occurs, it must be solved by the sync branch. Finally, the whole project can be merged into the develop branch.

Syncing branches


How it looks in practice

Assuming you’ve already created your repository, now you need to create the branches. In our process, we start with only the master branch. The first step is to create the develop branch and then switch to it at once.

$ git checkout -b develop

Switched to a new branch ‘develop’

At the level of the develop branch, we now create a new feature branch, called feature-123, for the proj project.

$ git checkout -b proj/feature-123

Switched to a new branch ‘proj/feature-123’

Now, as an example, let’s add a test file: test.txt.

$ git status

On branch proj/feature-123

Untracked files:

 (use “git add <file>…” to include in what will be committed)


nothing added to commit but untracked files present (use “git add” to track)


Next, ask Git to add the new file to the tracked list…

$ git add test.txt


…and then commit the newly created file to the local repository.

$ git commit -m ‘[feature-123] This is a test file’

[proj/feature-123 a299e93] [feature-123] This is a test file

1 file changed, 0 insertions(+), 0 deletions(-)

create mode 100644 test.txt


Supposing that the new file fulfills the Definition of Done and we’ve completed the work in this branch. Before creating a new branch in the GitHub repository, we merge it with the develop branch.

$ git merge develop

Already up-to-date.


All changes in the feature-123 branch have an up-to-date version of the develop branch. If any conflicts occur now, they must be solved by the feature branch. Now that the functionality is complete, we send it to the GitHub repository.

$ git push origin proj/feature-123

Counting objects: 12, done.

Delta compression using up to 4 threads.

Compressing objects: 100% (2/2), done.

Writing objects: 100% (2/2), 284 bytes | 0 bytes/s, done.

Total 2 (delta 1), reused 0 (delta 0)

remote: Resolving deltas: 100% (1/1), completed with 1 local objects.

* [new branch]   proj/feature-123 -> proj/feature-123


Finally, we insert a Pull Request for another developer to verify the code. This step is realized in the web interface at

If the code has been successfully verified by another developer, the change is added to the develop branch.


We’re constantly improving our skills and thanks to using Git to adopt various approaches to our work, we’re analyzing and implementing better and better solutions. It’s not enough just to use Git or branches based on the best practices, the solutions must be ideal for each individual project.

Here at XSolve, we would really encourage you to employ the Definition of Done, Code Review, and a series of manual and automated tests run on continuous integration tools. by taking measures like this, you will ensure that the software you’re creating is of the highest quality.


Featured Post Technology

Face Validator: open source Symfony3 face detection budle

Have you ever used an application to upload a profile picture? Sure you have. That picture then shows up with every reference to the user. In the systems we...

Business Featured Post

INFOGRAPHIC: How to create an Agile Office

A few months ago we wrote an article on how to create an agile office. It seems that you really liked our take on agile office and thus we decided to...

Business Featured Post

Which software companies do other CIOs work with?

A personal recommendation from someone you trust can be the biggest factor when faced with a difficult purchasing decision. Imagine a friend saying to you, “Honestly, this is the...

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies.

To find out more click here

Ok, Thanks