Software Engineering Stack Exchange is a question and answer site for professionals, academics, and students working within the systems development life cycle. It only takes a minute to sign up.
Sign up to join this community
Anybody can ask a question
Anybody can answer
The best answers are voted up and rise to the top
I will have to create a second app based on the first app. The second app shares 98% of the code (Some of the UI is different). I am wondering how to set up the second app without creating a merging hell. The files which are different are not in one place throughout the code tree. (The app is a flutter app – I don’t think that information madders)
Git is a version control system, which means it’s good at tracking the change history of your project. It’s not at all suitable for handling different editions of your software.
This means you should not necessarily model your use case through Git, but should take a step back and think about why you need two almost identical apps.
Sometimes, you just need some small fixes for another program. Then, you could create patch files that can be applied to the original project. This can actually be modelled via Git: you record your patches as commits on top of the other project, and then rebase as the other project updates. However, you will necessarily get merge conflicts if the original project changes the modified code. This is a good thing! However, it quickly gets extremely annoying and tedious if you have larger patches.
You can reduce the opportunities for conflicts by keeping most of the patched logic in separate files, and only modifying the original project files to include or call into your separate files. You should also leave as much of the original code intact as possible. E.g. don’t remove code that is unused in the patched edition.
Perhaps, you need to distribute different editions of your app, like a Basic and Pro version. At first glance, you might be tempted to take the Pro version, create a Git branch, and to remove all the code that’s not supposed to be in the Basic version. But that’s going to cause pain down the road. Instead, note that they are one application that are merely distributed/deployed in different configurations.
This difference should be applied at build time, not at coding time. E.g. in C, I might use
#ifdef PRO_VERSIONto include some code in the deployed application only if a certain build-time setting is enabled. In an OOP context, dependency injection has similar effects.
If you want ifdef-style source manipulations but are not using C, you could write some build scripts that assist with this. E.g. to create a release build, you could copy your entire source code into a separate directory, and then use a script to strip out parts of the files that shouldn’t occur in that edition. Then you build it. The parts that should be removed could be demarcated by special comments. Tip: put the removed code into a comment or replace it with blank lines, in order to keep line numbers intact.
Perhaps you need to quickly create many distinct apps that only differ in small details. In particular, if multiple apps just have different branding, or small changes in business logic.
In that case, you actually want to create a library or framework that makes it easy to create new apps. In simple cases, a single app that just loads a configuration file to apply specific settings is sufficient. In more complicated cases, you might need a full-blown plugin system. In any case, the idea is to recognize what kind of things you need to change between apps, and to make those things configurable instead of hardcoding them. This changeability would be a core requirement of your software.
There are some drawbacks to this approach. If you want to be able to update your shared library (which contains the main app code), you need to pay close attention to backwards compatibility. In some cases, a potential solution is to use a monorepo approach, that all apps and the shared library are developed together. That way, you can modify the shared library and in the same step also update all dependent code accordingly.
I didn’t always know about this. I worked on a project where we needed different editions of the software for different clients. We couldn’t use solution #2 because the clients got the source code. We should have used solution #3 and created a plugin system for customer-specific changes. We actually created different Git branches, which wasted an insane amount of effort (I’d guess ~20% of the entire development effort). The different editions diverged more and more, and were basically impossible to merge after a few months. It was also difficult to implement cross-cutting concerns, like changing the CI configuration for all editions.
Not the answer you’re looking for? Browse other questions tagged git github or ask your own question.