This practical guide helps Joomla beginners adopt version control and modern build practices for extensions (modules and components). You will learn how to structure a repository, use a simple Git branching strategy, create reproducible installer zips, automate packaging with CI, publish updates, manage database changes safely, and decide when a feature should be a module or a component.

Throughout the article you will find concrete examples, checklists and warnings for steps that can break a live Joomla site. Verify Joomla-specific configuration details against the official Joomla documentation before applying changes to production.


Why use version control for Joomla extensions?

Benefits of Git: history, collaboration, rollbacks and code review

Version control systems such as Git provide core benefits that apply directly to extension development:

  • Change history: see who changed what and why, and link commits to issues.
  • Branching: isolate features, bug fixes or experiments on separate branches.
  • Revertability: roll back problematic releases quickly.
  • Code review and CI: use pull requests and CI checks to improve quality before merging.
  • Reproducible releases: tags and release artifacts (zips) make releases repeatable and traceable.

Common beginner concerns and quick wins

  • Start small: one repository per extension (module or component) is a good default.
  • Use a simple branching model: main (stable), feature/* branches, and release tags (v1.0.0).
  • Use .gitignore to avoid committing local configs, build outputs and credentials.
  • Automate the zip creation in CI rather than zipping by hand — this reduces human error.

Practical examples

  • Example flow: create a feature branch, modify a module view, open a pull request, run CI checks, merge to main and tag v1.0.0 for release.
  • Example .gitignore entries: node_modules/, vendor/ (if you rebuild vendor), .env, build/, and .idea/ or other IDE folders.

Warnings

  • Never commit site configuration or admin credentials to a public repo.
  • Avoid storing full database dumps in the repository; prefer migration scripts or backups stored separately.

Repo layout and workflows: single-repo vs per-extension

Tradeoffs and recommended default

Two common layouts are monorepo (many extensions in one repo) and per-extension repos. For most beginners, a per-extension repo is simpler: smaller clones, focused CI and independent release cadence. Consider a monorepo only when extensions are tightly coupled and you need atomic cross-extension changes.

Monorepo pros and cons

  • Pros: unified dependency management, easier coordinated changes, single CI pipeline.
  • Cons: larger repo, more complex CI, harder to manage permissions per-extension, and possible longer build times.

Per-extension repos pros and cons

  • Pros: focused CI, simpler permissions and releases, fast clones and clearer ownership.
  • Cons: cross-extension changes require coordination across repositories.

Example repo structure guidelines

Keep the source layout roughly reflecting the eventual installer zip to simplify packaging.

Warnings

  • Do not include vendor libraries in the repo unless you intentionally ship them — prefer rebuilding dependencies during packaging or using Composer when appropriate.
  • Avoid committing large binaries that will bloat repository history.

Recommended Git workflow and branching strategy

Branching model

A practical, beginner-friendly model:

  • main (stable, protected): only merged changes via PRs after CI passes.
  • feature/*: short-lived branches for new features or fixes.
  • Tags like v1.2.0 identify releases and should correspond to packaged artifacts.

Versioning conventions

Use Semantic Versioning as a guideline: MAJOR.MINOR.PATCH. Document your version policy in the repository README.

Practical commands

Warnings

  • Ensure the version in your extension's manifest matches the release tag before publishing; mismatches can cause update problems.
  • Protect the main branch and require CI to succeed before allowing merges to avoid shipping broken code.

Packaging a Joomla extension: manifest, files and creating the zip

What to include in the installer zip

The installer zip should contain only runtime files the Joomla installer expects: PHP source files, language files, assets, templates, and any SQL install/update files. The manifest XML (module or component) controls what gets installed and must be included in the package at the location Joomla expects.

What to exclude

  • Development-only files: tests, CI configs, source maps.
  • Local config files and credentials.
  • .git directories and other VCS metadata.

Build script basics

Create a reproducible build script (bash, Node or PHP) that:

  1. Creates a clean temporary build directory.
  2. Copies only the runtime files into that directory in the correct layout.
  3. Updates the manifest version if required.
  4. Creates a zip archive with the proper root structure for Joomla installer.

Practical example (bash outline)

Warnings

  • Verify the zip root folders match Joomla's installer expectations; an incorrect structure causes installation failures.
  • Do not include .git or CI secrets in the zip.

Please verify the exact manifest elements required for modules and components against the official Joomla documentation before publishing packages.

Automating releases: CI/CD examples to build zips and publish

CI job stages

A typical CI pipeline for extensions includes steps to:

  1. Checkout the repository.
  2. Install build dependencies (if any).
  3. Run linters and tests.
  4. Run the build script to assemble the package zip.
  5. Upload the zip as an artifact and optionally publish it to a release or file server.

Tag-driven releases

Configure CI to trigger the packaging job on pushed tags (for example, tags starting with v). This ensures the built artifact version matches the git tag and helps keep releases traceable.

GitHub Actions / GitLab CI outline

Example YAML outline (conceptual):

Security and publishing

  • Store publishing credentials in CI secret stores and avoid printing them in logs.
  • Publish artifacts to appropriate targets: GitHub Releases, an internal file server, S3 or a dedicated update server based on your distribution needs.

Warnings

  • Do not expose secrets in logs. Rotate tokens regularly.
  • If you publish to a public channel, ensure licensing and attribution comply with Joomla Extensions Directory (JED) rules.

Distributing updates: Joomla update manifests, update servers and Composer

How Joomla update discovery works (concept overview)

Joomla can discover extension updates via update manifests or update server endpoints that point to new package URLs. You typically publish a small update XML that lists available versions and download URLs; Joomla's Extension Manager checks these endpoints and lists updates in the admin UI.

Update server workflow

  1. CI produces a release zip (e.g., v1.2.0).
  2. You upload the zip to your server or storage (S3, CDN, etc.).
  3. You update the update.xml (or equivalent) to include the new version entry pointing to the zip URL.
  4. Joomla sites configured to check your update URL will see the new version available.

Composer vs installer zip distribution

Composer distribution is an alternative for sites that use Composer-based Joomla installations. It provides fine-grained dependency management for developer-oriented setups, but many site administrators still prefer the standard installer zip. If you offer Composer packages, provide clear instructions and consider supporting both distribution methods when practical.

Warnings

  • Ensure the update XML's version and download URL are accurate—incorrect entries can prevent updates or show incorrect versions to users.
  • Do not enable automatic updates in production for critical extensions without staged testing and rollouts.

Verify the exact format and fields required for Joomla update manifests with the official documentation before integrating automated update publishing.

Module vs Component: a decision checklist

Use this practical checklist to decide whether to implement a feature as a module or a component.

High-level rule

Components are for application-like functionality with multiple views, backend management, and usually custom DB tables. Modules are for small frontend widgets or blocks that are assigned to template positions.

Decision checklist (6 questions)

  1. Does the feature need a dedicated admin UI? If yes → lean component.
  2. Does the feature require custom database tables? If yes → consider component.
  3. Is the output a small block that appears in template positions? If yes → module.
  4. Will you need multiple views and custom routing? If yes → component.
  5. Is granular ACL integration required? If yes → component.
  6. Would a hybrid approach (component for data/manage, module for widgets) be cleaner? If yes → consider both.

Examples

  • Announcements banner across the site — module.
  • Event management with bookings, reports and admin screens — component.
  • Component + module hybrid: component stores events and provides APIs; small modules render upcoming events in positions.

Warnings

  • Avoid implementing complex business logic only inside modules; maintainability and testing will suffer compared with components.
  • If you plan to use custom DB tables, verify Joomla's recommended locations and naming for SQL install/update files before publishing.

Handling database changes and migrations safely

Approaches

Two common approaches for schema and data migrations:

  • SQL install/update files that run declarative SQL changes.
  • Installer script classes (PHP) for complex or conditional migrations.

Best practices

  • Make migration steps idempotent where possible (safe to re-run without breaking).
  • Keep update files ordered by version and document the sequence clearly.
  • Test all migrations on staging with a copy of production-like data.
  • Always take backups before applying migrations to production.

Practical example (organization)

Place sequential update files in a versioned folder like sql/updates/mysql/ and name them by target version (for example, 1.1.0.sql). Reference the update files from the manifest as required by Joomla.

Warnings

  • Database migrations can irreversibly change production data — require staging tests and a recovery plan.
  • Do not rely on untested installer scripts for major data transformations.

Confirm Joomla conventions for SQL update file locations and naming in the official docs before releasing upgrades that change the database schema.

Practical tools, starter kits and resources

Developer tooling examples

  • Scaffolders: use a generator to create a standardized module or component skeleton to speed development.
  • Packaging helpers: small scripts to copy runtime files into a build folder and create zip archives.
  • Static analysis: PHPStan or Psalm to catch issues early; integrate into CI.
  • Testing: add PHPUnit or integration tests where feasible and run them in CI.

Where to find starters and docs

Consult the official Joomla Extension Development documentation, manifest guides and update server documentation for authoritative details. Check community starter kits and scaffolding projects, but verify they follow current Joomla best practices.

Warnings

  • Verify tool versions for compatibility with the Joomla version you target.
  • Be cautious using third-party starters with outdated patterns; review the code before adopting.

Step-by-step example: from dev repo to release zip

End-to-end sequence

A concise, reproducible sequence for a release:

  1. Create feature branch: git checkout -b feature/x.
  2. Implement changes and open a pull request.
  3. Run CI checks and merge to main after approval.
  4. Bump the manifest version (e.g., to 1.2.0) and update CHANGELOG.
  5. Create an annotated tag: git tag -a v1.2.0 -m "Release 1.2.0" and push tags.
  6. CI detects the tag, builds the zip and uploads it as a release artifact.
  7. Update your update.xml on the update server pointing to the new zip URL so Joomla sites can discover the update.

Release checklist

  • All tests and linters passed in CI.
  • Manifest version matches the git tag.
  • Changelog updated and release notes created.
  • Release artifact (zip) attached to the git tag/release.
  • Update server entry updated (if applicable).

Warnings

  • Do not push a tag without ensuring CI will create and attach the corresponding artifact — mismatched tags and missing zips confuse users.
  • Confirm update server updates are atomic and tested to prevent leaving users with broken update entries.

FAQ

Do I need Git for Joomla extension development?

Yes. Git offers history, safe branching, rollbacks and reliable release tagging. Even single developers benefit from tags and repeatable packaging.

Should each extension have its own repository or should I use a monorepo?

Both approaches are valid. Per-extension repos are simpler for beginners and independent releases. Use a monorepo if extensions are tightly coupled and you need atomic, cross-extension changes.

How do I create the zip install package for Joomla from my codebase?

Create a reproducible build script that copies only runtime files into a clean folder, ensures the manifest version is correct, and zips the folder. Automate this in CI to reduce errors.

When should I build a component instead of a module?

Choose a component when you need admin interfaces, multiple views/controllers or custom DB tables. Use a module for simple frontend blocks or widgets. Consider a hybrid when a component manages data and a module renders small pieces of that data.

How do I handle database schema updates for my extension?

Use Joomla SQL update files for straightforward schema changes and installer script classes for complex migrations. Test migrations on staging and keep backups. Verify Joomla naming and placement conventions before releasing updates that change the schema.

Conclusion

Adopting Git and simple CI for Joomla extension development makes releases reproducible, traceable and safer to maintain. For most beginners, a per-extension repository, a minimal branching policy and an automated packaging script are the best starting point. Use the module vs component checklist to pick the appropriate extension type, and treat database migrations and update publishing with extra care. Before applying Joomla-specific configurations (manifest fields, update XML format, SQL file placement), verify the details against the official Joomla documentation.

Additional checklist (quick reference)

  • One repo per extension (default) or monorepo if tightly coupled.
  • Protect main and require CI for merges.
  • Automate packaging and publish artifacts from CI on tags.
  • Keep only runtime files in the installer zip; exclude dev artifacts.
  • Test database migrations on staging and keep backups.
  • Verify all Joomla-specific manifest and update-server details against official docs before publishing.

Add comment

Submit