← All posts
gitdotmwddeveloper-toolsgit

GitDot: Subgroups for Any Git Platform, Using Only Repository Names


If you keep one package per repository, you soon have a lot of repositories. The first MWD post explains why we work that way. This post covers the tool we built for the problem it creates: GitDot.

GitDot is an experiment, and we’re no longer actively developing it. We’re writing it up here so the idea and the basic usage stay in one place. Its old documentation site now points to this post.

The problem: a flat list of repositories

When you build many packages, you have two options.

  1. Monorepo. Every package lives in one repository. Folders give you structure for free, but the history of all packages ends up in one log, and CI has to work out which part of the tree changed.
  2. Multi-repo. Each package gets its own repository, with its own history and its own releases. The separation is clean, but you now have dozens or hundreds of repositories.

The second option is the better architecture, but the Git hosts don’t help with the structure. On GitHub, an organization is a single flat list of repositories, with no nesting. GitLab has subgroups, but that only helps if you’re on GitLab and are happy to model everything as groups. Plenty of teams keep their code on GitHub for its visibility in open source.

The idea: put the hierarchy in the name

GitDot needs no feature from the platform. It reads the structure from the repository name, treating each dot as a folder separator.

Say an organization has these repositories:

my-org/
├── core.auth.service
├── core.auth.oauth
├── core.auth.jwt
├── api.gateway
├── api.users
└── api.orders

GitDot shows them like this:

my-org/
├── core/
│   └── auth/
│       ├── service
│       ├── oauth
│       └── jwt
└── api/
    ├── gateway
    ├── users
    └── orders

Nothing is moved or migrated. The repositories stay exactly where they are on the host, and GitDot hosts nothing itself. It’s a read-and-display layer on top of the platform you already use. Since the hierarchy is part of each name, it also appears in every clone URL and every reference to the repository.

We use this naming for our own repositories. The first post shows our glpkg.* repositories as GitLab lists them and as GitDot shows them, and git-nested can draw a workspace as a tree using the same dotted names.

Using it

GitDot runs as a web app at beta.gitdot.microwiseai.com and supports GitHub and GitLab.

  1. Open the app, sign in, and connect your GitHub or GitLab account. GitDot asks for access to your repositories and organizations so it can list them. Private repositories are supported.
  2. Go to Repositories. Pick one of your organizations or groups on the My Organizations tab, or type an organization name on the Direct Input tab.
  3. GitDot fetches the repositories and shows them as a tree, split on the dots.

To use the hierarchy, rename them to dot notation:

  • GitHub: repository Settings → change the name (for example auth-service → auth.service). Update anything that points to the old name.
  • GitLab: Settings → General → change the project name and path. GitLab sets up redirects from the old path.

GitHub, GitLab and Gitea all allow dots in repository names, so the naming works on any of them. The GitDot app itself only connects to GitHub and GitLab.

Naming conventions

The syntax is simply <domain>.<subdomain>.<name>, for example auth.service, auth.oauth.google or api.v2.users. What matters is picking a grouping and sticking to it. Three patterns work well:

# by domain          # by layer           # by feature
billing.service      core.database        checkout.cart
billing.webhook      core.cache           checkout.payment
users.service        api.gateway          search.indexer
users.profile        web.dashboard        search.query

A few rules we follow:

  • Lowercase, concise names. Prefer singular nouns where they read naturally.
  • Dots for hierarchy, hyphens inside a segment. auth-service is one name. auth.service is service inside auth.
  • Four levels at most. Deeper trees get harder to navigate than the flat list you started with.
  • One pattern per organization. Mixing domain-first and layer-first names breaks the tree into two half-trees.

For versions, either put the version in the name (api.v1.users, api.v2.users) or keep one repository and use tags (api.users tagged v1.0.0, v2.0.0) and keep the names clean.

Migrating existing repositories is a rename:

BeforeAfter
auth-serviceauth.service
user-api-v2api.v2.users
frontend-dashboardweb.dashboard

On GitLab you can combine both approaches. Use native subgroups for the top level, and dot notation inside a subgroup for finer structure.

Where GitDot stands

GitDot is part of Microwise Labs: something we built, use and share, but which we don’t actively maintain. The beta does one thing: it connects GitHub or GitLab, parses dotted names, and shows your organizations’ public and private repositories as a tree.

We once planned more: batch renames and group moves, a CLI, and editor integrations. We’re not working on those now, so please don’t count on them. The beta is still up and you’re welcome to use it, but it may change or go away without much notice.

The part we’re sure will last is the naming convention. It needs no tool at all. If your repositories are named area.sub.name, the structure is in the names, and any tool, script or person reading the list can recover the tree with split("."). GitDot is one way to see that structure.

If you try it, or you’ve solved the same problem differently, we’d like to hear about it in our feedback discussions.