0%
gitsoftware-engineering

Organizing Many Projects

I do independent development for both work and pleasure across several languages and frameworks.

I usually break my work into several broad categories of project type: product, library, learning, experimental, and templates. In addition I sometimes fork other OSS projects for examination or minor bug fixes.

I also work across a few machines to suit different work conditions (local dev laptop, local dev on desktop and remote workstation).

This results in a fairly large number of distinct code projects to manage in at several locations.

I get easily distracted and lose focus, so I am particular in defining and using patterns to help organize and reduce the cognitive load and diffusion navigating across these dimensions can cause. Consistent hierarchical categorization and placement, naming conventions, etc.

This results in a sort of ‘meta-project’ organization that I prefer, which also tends to evolve over time as I decide on re-categorization or further refinements in support tooling.

Options

There are of course an infinite different number of ways to organize, and I’ve tried many.

Manual Management

This was the very thing that I found burdensome and distracting. I tend to slowly evolve my organization over time. That with the fact that I bounce between machines so much, that things would desynchronize enough that it would disrupt my flow.

Management Scripts

Nothing about my structures are complicated beyond some fairly simple scripts. But I do tend to evolve things at a steady pace so it did mean some constant updates and tweaks. Working across machines, you then have to keep the management scripts in sync as well. Like many things, LLM assisted coding does make this much easier so it’s not a huge burden but I wanted to do something with less overhead.

Monorepo

I went to a monorepo for a brief period but this ultimately proved too heavy weight. To support the various types of projects I ended up wanting or having to build more complicated tooling then I wanted to. While this has gotten vastly easier with LLM assisted coding, I found the tooling overhead when combined with the ‘smearing’ of commit history across all projects less than idea.

I DID very much enjoy the moon tool and will continue to use it for appropriate use cases. I think I may apply it across my submodule solution as well for certain cross-cutting ‘meta’ tasks.

Singular Development Server

I would consider moving but I am working on some desktop applications that target multiple platforms which makes this a no-go as a total singular solution.

‘Meta-repo’ and Submodules

Blending the approach of entirely isolated git repositories and a monolithic ‘monorepo’, I have settled on a single ‘dev’ repository structure for meta-organization and embedding my other projects with git submodules.

It looks something like this:

dev (its own repository)
  companyA
    customer1project
      docs
        plans
        todo
      repo (submodule)
    customer2project
      docs
      repo (submodule)
  companyB
    productA
      planningDocs
      repo (submodule)
  oss
    projectA
      repo (submodule)
    projectB
      repo-public (submodule)
      repo-private (submodule with in progress work)
  templates
    template-tauri-project
      repo (submodule)
    template-astro-project
      repo (submodule)

It’s not perfect. There is still the likelihood of drift between workspaces, and git submodules can be a bit unwieldy if you make a mistake.

However the single canonical organizational structure with isolated git work history is proving the best approach i have found so far.

Advantages

Canonical organizational structure

Existing Tooling

No scripts or additional configuration files to write or manage. It is simply just folder structure and git.

Conceptual Isolation

Projects retain their own independent work history. It doesn’t get smeared or interleaved across a single monorepo. This wasn’t hard to deal with using various git log filter tools, but it is one less thing to have to deal with.

Cross Cutting Tooling

I like to try to maintain project similarity with regards to tasks, build actions, ci, etc.

Once I download the parent repository, and then properly initialize it I can perform cross cutting updates easily enough.

NOTE: You will have to perform multiple commits and pushes however. See [[#Unweildy|below$a.])

  • Still allows cross cutting tooling

Cons

Error Prone (at first)

It required learning and understanding how git implements submodules as I made some mistakes and ended up in some inconsistent error states in my repository early on. (More coming in another post) It is well explained in the herehowever.

Unwieldy

You need to ‘double-commit’. If you make changes in a submodule you have to commit and push those changes, and ALSO be sure to commit and push changes in the parent module (as it retains a pointer to the particular submodule hash)