Git Repository Naming Conventions: A Practical Guide for Teams
A repository name is the cheapest piece of documentation your team will ever write, and the one most likely to outlive everyone who chose it. Six months after a project starts, project-x tells a new hire nothing, while billing-api tells them what the thing does, roughly how big it is, and whether they should care.
This guide covers a naming convention that works for teams of three to thirty, how to handle the messy names you already have, and how to rename a repository without breaking anyone's clone.
Why repository names rot
Repositories are created in a hurry. Someone needs a home for a prototype before a meeting, so it gets called test or new-stuff. The prototype ships. The name stays. A year later there are four repositories that could plausibly be new-stuff, and the only person who knows which one runs in production has just left.
The cost shows up in small ways that compound: onboarding takes an extra week, the wrong repo gets patched during an incident, a CI pipeline points at an abandoned fork, storage and seat costs creep up. None of these are dramatic alone. Together they are why "which repo is the real one?" becomes a recurring meeting.
The core rules
You do not need a thirty-page standard. You need six rules that survive contact with reality.
1. Lowercase, hyphenated, ASCII only
Use kebab-case with plain lowercase letters, digits and single hyphens. It is the only style that behaves identically in URLs, in file paths, in Docker image names, in Terraform module sources and on Windows checkouts. Underscores survive most of those but not all; dots are worse; spaces and capitals invite case-sensitivity bugs.
good: billing-api
bad: Billing_API
bad: billing api
bad: BillingApi.v2
2. Lead with the domain, then the component
Put the business area first and the technical role second. That way a sorted list groups naturally: everything about billing sits together, and inside that group you can see the API, the worker and the dashboard.
billing-api
billing-worker
billing-admin
identity-service
identity-migrations
The reverse order (api-billing, api-identity, worker-billing) groups by technology, which is less useful: nobody opens a repository because they want "an api", they open it because they want billing.
3. Encode the role with a closed vocabulary
Pick a short fixed list of suffixes and stop inventing new ones. A workable set:
-api— a service other things call over the network-worker— background jobs, queues, crons-web/-app— user-facing front end-lib— a shared library or package other repos depend on-infra— deployment, Terraform, Kubernetes manifests-docs— documentation that outgrew a README-proto/-schema— contracts and migrations-archive— retired code kept for reference (see below)
Eight suffixes cover almost everything. When a new repo does not fit, the answer is usually that it is two repos or that one of the existing suffixes already works.
4. Never put a version number in the name
billing-api-v2 is a promise that v3 is coming and that both will live forever. Branches, tags and releases express version. A name that carries a version guarantees a migration nobody wants to do.
The one exception: when you genuinely run two services side by side during a rewrite, name them by what they do rather than by number — billing-api and billing-ledger-api — and delete one when the migration finishes.
5. Keep names short enough to type
Thirty characters is a reasonable ceiling. If a name needs three hyphens to be precise, the repository probably has two responsibilities. Longer names also break tooling that truncates labels — dashboards, CI badges, container registries.
6. Prefix shared or example repos
Repos that exist for the whole organisation, not one product, get a prefix: shared-, example-, sandbox-. Prefixes sort together and make it obvious that a repo is not on the critical path.
shared-eslint-config
example-fastapi-service
sandbox-playground
A naming convention you can write on a card
| Part | Rule | Example |
|---|---|---|
| Domain | One or two words, the business area | billing |
| Role | From the closed suffix list | -api |
| Qualifier (optional) | Only when two things share a domain and role | billing-ledger-api |
| Case | Lowercase kebab-case, no version numbers | billing-api |
| Ceiling | 30 characters, three hyphens max |
Organisations, teams and owners
Names do one job; ownership is a separate field. Do not try to encode the team in the repository name — teams get renamed and reorganised far more often than products do, and a name that says growth-team-notifier becomes a lie in one reorg.
Record ownership somewhere queryable instead: a CODEOWNERS file, a repository topic or label, or a line in your inventory sheet. The rule of thumb: if the fact changes faster than the code, it does not belong in the name. Domains and roles are durable. Teams, vendors and clouds are not.
This is where most conventions fail. A naming standard that encodes reorg-prone facts needs a renaming project every time the company changes shape. Keep the name about the domain and the code's role, and put everything else in metadata.
Handling the repositories you already have
You are not starting from zero. Renaming two hundred repos in one week creates two hundred broken links, CI badges and deploy configs. Do it in three passes.
Pass 1 — inventory
List every repository with: name, owner, last commit date, whether it deploys to production, and who would notice if it disappeared. This list is worth more than the convention itself. Most teams find between 30% and 60% of their repositories have had no commits in a year.
Pass 2 — triage into four buckets
- Keep and rename — active, poorly named.
- Keep as is — active and already fine; do not touch working names for style points.
- Archive — no longer changes but worth keeping readable.
- Delete or merge — duplicates, forks of forks, spikes that never shipped.
Pass 3 — rename with redirects
On GitHub, renaming a repository inside the same organisation sets up a redirect from the old URL, and old clones keep working with a warning until someone pushes. That makes renames cheap if you do them one at a time and let CI settle in between. The riskier rename is a move between owners — that one breaks clones and needs a coordinated push.
A safe rename checklist:
- Grep your org for the old name: CI configs, Dockerfiles, Terraform, deploy scripts, docs.
- Rename, then immediately push a trivial commit to confirm redirects and pipelines still resolve.
- Update dependency references and container image paths the same day.
- Add the old name to the repository description ("formerly
billing-service") for one quarter.
Naming in a monorepo world
If you are consolidating into a monorepo, the naming problem moves rather than disappears. Package and directory names inside the repo now carry the load, and the same rules apply: domain first, role second, closed suffix list. Keep the pattern identical to what you used for standalone repositories so people do not have to learn two conventions.
Making it stick
Conventions die when they are only written down. Three habits keep them alive:
- Name it at creation. Put the convention in your repository template and in the "new repo" checklist. A bad name that exists for one hour is easy to fix; one that exists for a quarter is not.
- Review the list quarterly. Fifteen minutes per quarter, sorted by last commit date, catches drift before it becomes archaeology.
- Fix names opportunistically. When you touch a repo anyway — a dependency bump, a migration — fix the name in the same piece of work.
The short version
Lowercase kebab-case, domain first, role from a closed list of eight suffixes, no version numbers, thirty characters maximum, ownership recorded outside the name. Inventory before you rename, rename with redirects, and re-read the list once a quarter. That is the whole convention — and it is enough to make a repository list answer the question new hires actually ask: what does this team own, and where does it live?
If you would rather not run that inventory yourself, that is what we do at repos.to: we map every repository, propose names, archive the dead ones and hand you a list you can trust.