using git in embedded software development

Why using Git-Flow?

When talking about adopting agile development, continuous integration, continuous delivery and DevOps practices, having a proper version control system and setting up the right workflow is one of the basic things to tackle. It takes you through most parts of the Dev-Test-Operation building blocks — code, build, test and release. Researches of SW R&D teams show significant improvements reducing time to market for new features when proper source control practices are implemented [1].

Today the most popular version control system for agile teams is Git. In this blog post, I’ll cover Git-Flow in embedded software development.


Git-Flow diagram
image was taken from —

For us at Jumper, after trying a few git workflows, we’ve decided to work with Git-Flow as proposed by Vincent Driessen (If you are not familiar with Git-Flow I encourage to read about it).

In a nutshell, Git-Flow is designed largely around the release and advocates to splitting your work between two main branches:

Master: What is currently in production — the stable branch.
Develop: The next set of features we are working on — the bleeding branch.
Git-Flow also talks about few supporting branches and how everything connects together.

We find this workflow, though it might seem a bit cumbersome, to be very useful for embedded software projects. On Web or Mobile application, you might not need one or more of the development, release and master branches. However, embedded software cannot be deployed all the time as physical devices are not always ready for an update. Another reason is that software updates might need to be certified. We find the master, release and development branches to be of a necessity when you are not deploying all the time.

Think about what happens when you find a bug in production but the time from a readily deployable package into actual firmware update on the field is days or weeks. During this time your development team is working on the next set of features. If you merge directly into master, but you’re not ready to release all your features yet and a bug is found in production — you’re stuck having to go back to the tag that’s in production, branching that, testing, releasing the branch, and then merging in. With a develop branch this isn’t an issue. New features are on developHotfixes are branched off master, and then merged into master and develop when finished.

Can I get the same benefits with tags?

Git-Flow provides a clear separation of concerns for new feature development, ongoing general maintenance, each release window, and emergency maintenance. Master is the holiest of holies and must remain in a pure, working, deliverable state at all times. Sure, we could technically achieve the same thing by tagging the releasable commits, but the separate branches provide a clear distinction, and that is beyond invaluable in embedded software development.
It’s also useful to see what you’ve released, what you’re about to release, and what features are yet to be included.

Embedded Software Development Constraints

Developing software for embedded systems introduces constraints that have an effect on your Git and software development workflow. We think that the three ones below are the common ones for most embedded systems projects:

  1. Hardware ConfigurationDuring a project lifetime, you need to support different hardware configurations, meaning you need to maintain different software versions.
  2. Certification Time — Certification process which is a must for medical, automotive, industrial, etc., introduce long test cycles before a release, meaning merging to master is postponed.
  3. Automated TestingThe physical device makes hooking up an automated testing process to a Git workflow cumbersome.

All three constraints are related to the Git workflow you choose. The third one also requires a testing framework that will allow you to run automated testing for embedded software products.

If you want to have an easy way of automating your physical device’s embedded software testing and move to agile development, you’re invited to try Jumper.

Hardware configuration

During an embedded product lifetime, you might have a different hardware configuration that is deployed for a different type of customers, or even for the same customer. This usually means you’ll need to have different versions for these sub-products while using the same repository. One might choose to work with more than one master and develop branches, but we don’t recommend it. When trying to maintain different branches you find yourself creating a unique build, separate testing, hard features merging, etc. All this translates to efficiency loss.

In these types of projects, the main challenge is usually in the interactions between the versions and how to effectively share code between them. When designing the Git-Flow it was not taken into account.

As there’s no silver bullet to address this with Git in general, we’ll outline few approaches for you to choose from.

  1. Split the code base into unrelated libraries/modules that support different configurations, manage them separately and then do configuration management. Note that you’ll need to invest in proper software architecture and abstraction layers.
  2. Control different configuration with features flags on the same branches.
  3. Create isolated and long-lived branches for each version/hardware configuration.

For the long run, we’d recommend on using the first two approaches together. It will also make your code much better and save you time on testing.

Certification Time

For products that must meet with regulation needs, the certification time might take weeks before a release. During this time you want your team to continue merging and working on the next features, while not adding noise to the certification release process. For this, the Git-Flow works like a charm.

Automated testing

Having a good Git workflow without hooking an automated testing process into it, is like doing only part of the job. You need to define a process where different types of tests run on different branches so you’ll have good coverage and efficiency in testing runtime. As you commit and merge a feature up the branches chain — from the local feature branch to remote repo, to develop, release and master you need to add more tests to complete the regression run.

As each project has unique testing requirements and available testing resources, we’ll outline our testing flow, which might need few tweaks to fit your project. Our testing flow is based on the assumption that you can at least run non-host testing, simulated host testing and HiL testing [2].

Appropriate Git-Flow usage for each embedded software tests

Note to set your automation manager to not run the same test twice on the same commit.

Interested in easy embedded test automation?

If you work with embedded systems and want to have an easy way of testing your physical device’s embedded software, you’re invited to try Jumper. Jumper allows you to have simulated host testing to boost your entire R&D cycle.


Adopting the right Git workflow is something you need to evaluate carefully. There’s not one size fits all here, and it depends on your unique product requirements. We hope that our proposed workflow will be beneficial for your needs. Let us know your thoughts and share with us your Git workflow.