12

Currently I am working on a project to make a product for company X. The team I am working with is selling similar service to many company with similar product, where 40% of the code is reused and 60% customized feature made to particular company. Previously there were no version control until I suggest using git recently. We are happy that we don't need to copy and paste each other's work repeatedly after introducing Git, but now we are a bit confused that should the new project be open as a new branch of previous product's repository (i.e. one repository for all products to different company) or as a new stand alone repository (i.e. one repository for different products)

Normally we are not merging the products of different companies, but sometimes when we find some good and commonly-wanted features, we would like to add those features to all the products of different company as a gift(once or twice per year). In this case, will it be better to open a new repository or just start a new branch?

1
  • 8
    Is it possible to split the codebase into a part that is common to all products and separate parts with the customizations for each product? Or is it possible to identify a "base product" that all product customizations start out from? Commented Dec 30, 2015 at 11:17

4 Answers 4

12

40% of the code is reused and 60% customized feature made to particular company

This might take a little time to actually get to the point that you can do this, but I think it should be a goal to extract that 40% out and make it its own repository. This is your main library/framework from which to work.

Then, that other 60% can be in dedicated repositories on a per-client basis.

It sounds like your code base qualifies as "legacy," so I highly recommend picking up Working Effectively With Legacy Code by Michael Feathers for yourself and your team. It provides techniques for bringing code under test, which can also be used for creating a plan to extract your code out into a library.

How would you go about doing this starting now? Here's what I'd do:

  1. Make every client its own repository (or, if you're using something like Github or Gitlab to manage the git repositories, and you have several repositories for a client, you can create an organization per client, but we'll assume 1 repository per client).
  2. Take a class that I reuse a lot and extract it out (assuming an object-oriented approach, though a functional one should have similar principles). We'll use this to start the library repository (this makes it useful from day 1). If you don't have full classes yet, then that's where Feathers' book comes in, as it shows you how to make classes out of non-classed code. While we're at it, we can add some basic testing to ensure it still does what we expect it to do.
  3. Commit this extraction as its own thing, and you can use it as the template to replicate the change across all repositories.
  4. As I come across shared parts, I extract them out and add them to this library repository.
  5. As the library grows, and I find things that are used by some clients, but not others, I can work toward a modular approach, where larger features are extracted out into their own repositories and included as "modules" or "plugins" to the main system. Alternatively, if there are themes for particular groups of items (such as a bunch that deal with authentication or payment processing), I can extract those out to their own repositories. How you go, exactly, in this stage depends on the nature of your code and the direction you want to go with it.

The advantage of this system is that all you need to do is add that shared item into the library and wire up any hooks necessary to make it work, and it's available to all of the clients, no copy-pasta needed!

Why this instead of branches? While technologically, branches aren't much different from standalone repositories, convention differentiates between them. A repository is a complete project (with references of some sort, either via submodules or scripts, to dependencies), while a branch is generally a given state of the project. You branch when you want to add a feature, fix a bug, or make another kind of change, but the system itself is considered the same. You make a new repository when the project is considered a different one (in this case, for a different client, with its own customizations and whatnot).

A good example of this is Oracle OpenOffice vs LibreOffice. LibreOffice is a fork of OpenOffice, and is even maintained by the same people. However, LibreOffice, even when it was technologically identical to OpenOffice (when it was first forked), it was considered a different product. The team then stripped the Oracle branding from it and started LibreOffice's own development path, which is now distinct from OpenOffice. While the changes that have been made to LibreOffice could have gone into a branch in OpenOffice, since LibreOffice is considered a different project, it needed its own repository, instead.

4
  • So how do you start the "client repo" ? A fork ? How do you pull changes from the base repo ?
    – jsaddwater
    Commented Oct 29, 2019 at 15:05
  • Are you talking after things are extracted? Once things are extracted, they'd be added as a library, however your language handles that (ie - for PHP, you'd point to it in your composer.json file and bring it in with Composer; for JS you'd do the same in NPM/Yarn). If you haven't extracted yet, and can't bring the old system whole cloth in as a sort of temporary library until you extract things out, then you'd have to fork it.
    – Shauna
    Commented Oct 30, 2019 at 13:55
  • That said, I think it's worth noting that the concept of "forks" is a value-add from Github, et al, and not a concept in git, itself. Understanding that distinction might make it easier to understand and suss out the relationships between the different code bases. Forks are really just clones with an "upstream" remote (which is also how you bring in changes from upstream).
    – Shauna
    Commented Oct 30, 2019 at 13:57
  • I ended up choosing the fork with upstream setup for my client projects.
    – jsaddwater
    Commented Oct 31, 2019 at 10:50
3

There are two separate issues in your question:

  1. Start the new product in the same repository or open a new one for it?

This is a matter of taste. Some keep all products in a single, giant repo, some open a new repo for each separate unit (even if it contains only a single file). Some find a healthy balance between the two extremes.

For now I'd say put your common libraries in one repo and each, unrelated end-product in its own repo.

  1. Open a new branch or open a new repo?

This never should be the question. You may decide to put the new product in the same repo. In that case, you do open a new (feature) branch, start developing the product there and, when it's stable, you merge it back to the main branch and delete the feature-branch.

Most of the time you can think of git branches as long commits. Eventually they will be merged back to the main branch and you delete them.

On the other hand there are persistent, maintenance branches. But you won't do any feature development on them.

So my answer is: you may decide to add the new product to the same repo (with new product also living on the main branch) or create a new repo for it. But don't abuse the branching mechanism to develop a separate product in the same repo.

I recommend you to check out Atlassian's Git Tutorials

4
  • 3
    If you use branches to distinguish between each client's distinct version of your product, you cannot 'merge and delete' the branches. They will be perpetual. I think that's what the question is asking: should they be perpetual branches or their own repo?
    – Eric King
    Commented Dec 30, 2015 at 17:51
  • Yes, you cannot...I guess I should add a bottom line to my answer. Commented Dec 30, 2015 at 18:31
  • 1
    Keeping all the projects in one repository is not the SVN way: I have seen many times where each project or group of very closely related projects are in their own repositories. Neither SVN nor Git, as a technology, have a "preference" for how to group projects in repositories. The only issue here is separate repositories in Git will be faster if you only need to clone a subset of the total subprojects.
    – user22815
    Commented Dec 31, 2015 at 14:02
  • @Snowman: not the svn way - i think you're right, fixing it... Commented Dec 31, 2015 at 21:34
1

Conceptually, there's not much difference between your choices. As long as you have a common ancestor, you can fetch branches from two repos and freely merge/diff/whatever between them.

The main difference is in access control. It's pretty easy to control access at the repo level, and pretty difficult at the branch level. If you want to give clients access to only their code, you should create their own repo.

Of course, you can do both. Internally you can have a single branch for each customer, and have a script that pushes just that branch to an external repo the customer can access.

However, keeping a separate branch per customer is not generally the best way to architect your code. It makes it very difficult to maintain later. It's usually much more maintainable long term to split your code into reusable common modules that are all in master, then each customer gets a small custom part that pulls in the modules. Try and put as much code as possible into the common modules.

2
-2

It's actually encouraged to create a branch anytime you want. Here're some tips might be helpful:

  1. when you're experimenting an new idea on the codebase
  2. when you're trying to fix a bug
  3. when you're trying to refactored your code
  4. when you're merging with an external branch
  5. when solving conflicts
  6. your'e making a new release
  7. you just want to make a save-point for the current stage

There might be a long list. You can maintain a list of TOPIC branch for your group.

2
  • Well, the core idea while working with git is that it's really lightweight and easy to create a branch. Unlike, creating a branch with svn, which might copy a whole thing. Branching with git is simply working like a tag, there's technically no different for git. If what we're going to do might be really big different from the original work space, it's worthy a new fork.
    – Duzy Chan
    Commented Jan 1, 2016 at 2:03
  • The idea of branching should be following the design and development workflow, instead of whether the changes is big or small. Because it's very common that a bug was introduced by changing a single character. If your tiny changes is logically different from what you're doing at the moment, it should be done in a branch, since branching is easy and lightweight. The idea is to keep a traceable record in the repository, if it's logically non-related, it should be done in new branch for easy tracking.
    – Duzy Chan
    Commented Jan 1, 2016 at 2:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.