I am soon starting to maintain a line of products containing variants of the same embedded software. Since I\'ve been playing with git for one year and appreciate it very much,
I'd try to go for #defines as much as possible. With a proper code you can minimize the impact on readability and repetitions.
#define
But at the same time #define approach can safely be combined with splitting and branching, application of which depends on the nature of the codebase.