๐Ÿ“ฆ leog / git-setup-submodules

A script to setup git submodules from a configuration file

โ˜… 0 stars โ‘‚ 0 forks ๐Ÿ‘ 0 watching โš–๏ธ Apache License 2.0
๐Ÿ“ฅ Clone https://github.com/leog/git-setup-submodules.git
HTTPS git clone https://github.com/leog/git-setup-submodules.git
SSH git clone git@github.com:leog/git-setup-submodules.git
CLI gh repo clone leog/git-setup-submodules
Leo Giovanetti Leo Giovanetti chore(release): 1.1.1 e8e3a53 1 days ago ๐Ÿ“ History
๐Ÿ“‚ main View all commits โ†’
๐Ÿ“ .github
๐Ÿ“ tests
๐Ÿ“„ .gitignore
๐Ÿ“„ .versionrc.json
๐Ÿ“„ CHANGELOG.md
๐Ÿ“„ index.mjs
๐Ÿ“„ LICENSE
๐Ÿ“„ package-lock.json
๐Ÿ“„ package.json
๐Ÿ“„ README.md
๐Ÿ“„ README.md

Git Submodule Setup

npm version License

A CLI tool to automate Git submodule setup from a configuration file.

Quick Start

# Create a config file
echo "libs/shared-utils" > .git-setup-submodules

# Run the setup
npx git-setup-submodules

Overview

This tool automates the setup of Git submodules in your project based on a configuration file. It reads the configuration, checks access to the specified repositories, adds them as submodules at specified paths, and sets them to specific branches or tags.

Features

  • Automated Submodule Setup: Quickly add multiple submodules without manual configuration.
  • Customizable Paths and Branches: Specify custom local paths and branches or tags for each submodule.
  • Access Verification: Checks if you have access to the submodule repositories before adding them.
  • Clean Working Directory: Unstages submodule changes to keep your working directory clean.
  • Dry Run Mode: Preview what changes would be made without executing them.
  • Custom Config File: Use a different configuration file with --config.
  • Input Validation: Validates configuration and provides clear error messages.

Requirements

  • Node.js: Version 16.0.0 or higher
  • Git: Version 2.23.0 or higher (required for git restore --staged)
  • npm: Node Package Manager (usually installed with Node.js)

Installation

You can use the script as a local dependency in your project or run it directly using npx.

Option 1: Install as a Local Dependency

  • Navigate to Your Project Directory
cd /path/to/your/project

  • Install the Package
npm install git-setup-submodules --save-dev

Option 2: Run Directly with npx

You can run the script without installing it by using npx:

npx git-setup-submodules

CLI Options

git-setup-submodules [OPTIONS]

OPTIONS:
  -h, --help              Show help message
  -n, --dry-run           Preview changes without executing git commands
  -q, --quiet             Suppress non-essential output
  -c, --config <path>     Path to config file (default: .git-setup-submodules)
  -b, --default-branch <name>
                          Default branch when not specified (default: main)

Examples

# Standard usage
git-setup-submodules

# Preview what would happen
git-setup-submodules --dry-run

# Use a custom config file
git-setup-submodules --config ./submodules.conf

# Use 'master' as the default branch
git-setup-submodules --default-branch master

# Quiet mode (only show errors)
git-setup-submodules --quiet

Configuration

Create a configuration file named .git-setup-submodules in the root directory of your project. This file lists the submodules to be added along with their configurations.

Configuration File Format

Each line in the configuration file represents a submodule and follows this format:

<remote-path>[:<local-path>][#<branch-or-tag>]

  • <remote-path>: Path to the submodule repository relative to your Git remote URL base.
  • <local-path> (optional): Custom local directory name for the submodule. Defaults to the module name if omitted.
  • <branch-or-tag> (optional): Branch or tag to check out. Defaults to main if omitted.

Examples

  • Basic Submodule
libs/utils

  • Clones utils from libs/utils into libs/utils, checking out the main branch.
  • Custom Local Path
apps/website:site

  • Clones website from apps/website into apps/site, checking out the main branch.
  • Specific Branch
libs/logger#v1.2.3

  • Clones logger from libs/logger into libs/logger, checking out the v1.2.3 branch or tag.
  • Custom Path and Branch
apps/website:site#production

  • Clones website from apps/website into apps/site, checking out the production branch.

Comments and Blank Lines

  • Lines starting with # or // are treated as comments.
  • Blank lines are ignored.
  • Inline comments with // are supported.

Sample Configuration File

# Submodules Configuration

# Add the utils library
libs/utils

# Add the website app to 'site' directory on 'production' branch
apps/website:site#production

# Add the logger library at tag 'v1.2.3'
libs/logger#v1.2.3

// Add the helpers library to 'helpersLib' directory
libs/helpers:helpersLib

// Add the console app
apps/console

Usage

Running the Script

If Installed Locally

If you've installed the script as a local dependency, you can run it using npx:

npx git-setup-submodules

Alternatively, you can add a script to your package.json:

{
  "scripts": {
    "setup-submodules": "git-setup-submodules"
  }
}

Then run:

npm run setup-submodules

Using npx Directly

If you haven't installed the script locally, you can run it directly with npx:

npx git-setup-submodules

Script Workflow

  • Check for Existing .gitmodules
  • If .gitmodules exists, the script assumes submodules are already initialized and exits.
  • Read Configuration File
  • Parses .git-setup-submodules for submodule definitions.
  • Determine Remote URL Base
  • Retrieves the Git remote origin URL to construct full submodule URLs.
  • Process Each Submodule
For each submodule in the configuration:

  • Access Verification
  • Uses git ls-remote to check if you have access to the repository.
  • Add Submodule
  • Executes git submodule add --force to add the submodule.
  • Set Branch or Tag
  • Configures the submodule to track the specified branch or tag.
  • Update Submodule
  • Pulls the latest changes with git pull.
  • Unstage Changes
  • Runs git restore --staged to unstage the submodule and .gitmodules.
  • Summary Output
  • Displays a summary with counts of successful and failed submodule additions.

Troubleshooting

Common Issues

"Configuration file not found"

Make sure the .git-setup-submodules file exists in your project root, or specify a custom path with --config:

git-setup-submodules --config path/to/config

"Failed to get remote origin URL"

This error occurs when:

  • You're not in a git repository. Run git init first.
  • The repository has no remote. Add one with git remote add origin <url>.

"Access denied" errors

Check that:

  • Your SSH keys are properly configured (ssh -T git@github.com)
  • You have read access to the repository
  • The repository exists at the expected URL

".gitmodules already exists"

The script won't run if submodules are already configured. If you want to reconfigure:

# Remove existing submodules first
rm .gitmodules
rm -rf .git/modules/*
git config --remove-section submodule.<path>  # for each submodule

"git restore" command not found

The git restore command requires Git 2.23.0 or later. Update Git:

# macOS
brew upgrade git

# Ubuntu/Debian
sudo apt-get update && sudo apt-get install git

# Check version
git --version

Invalid characters in path

Module paths cannot contain shell metacharacters like ;, |, $, etc. Use only alphanumeric characters, /, -, _, and ..

Debug Mode

Use --dry-run to preview what commands would be executed without making changes:

git-setup-submodules --dry-run

Error Handling

  • Missing Configuration File
  • The script exits with an error if .git-setup-submodules is not found.
  • Git Repository Not Found
  • If the script cannot retrieve the remote origin URL, it exits with an error, indicating you may not be in a Git repository.
  • Access Denied to Submodule
  • If access to a submodule repository is denied, the script logs an error and continues with the next submodule.
  • Invalid Configuration Lines
  • Lines with invalid syntax or dangerous characters are skipped with an error message.

Logging

  • Progress Messages
  • The script logs the setup process for each submodule, including paths and branches.
  • Access Notifications
  • Informs you whether you have access to each submodule.
  • Final Status
  • Displays a summary message upon completion with success/failure counts.

Contributing

  • Fork the Repository
  • Create a fork to contribute changes.
  • Create a Feature Branch
git checkout -b feature/your-feature-name

  • Run Tests
npm test

  • Commit Your Changes
git commit -m "Add your feature"

  • Push to Your Fork
git push origin feature/your-feature-name

  • Open a Pull Request
  • Submit a pull request to the main repository for review.

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

Releasing

This project uses commit-and-tag-version for versioning and changelog generation. Releases follow Conventional Commits.

Commit Message Format

<type>(<scope>): <description>

[optional body]

[optional footer(s)]

Types:

  • feat: A new feature (bumps minor version)
  • fix: A bug fix (bumps patch version)
  • docs: Documentation only changes
  • style: Code style changes (formatting, semicolons, etc.)
  • refactor: Code refactoring
  • perf: Performance improvements
  • test: Adding or updating tests
  • chore: Maintenance tasks
Breaking Changes: Add BREAKING CHANGE: in the footer or ! after the type (e.g., feat!:) to trigger a major version bump.

Release Commands

# Preview what would happen (dry run)
npm run release:dry

# Create a release (auto-determines version from commits)
npm run release

# Create a specific version bump
npm run release:patch   # 1.0.0 -> 1.0.1
npm run release:minor   # 1.0.0 -> 1.1.0
npm run release:major   # 1.0.0 -> 2.0.0

# First release (if starting fresh)
npm run release:first

Publishing

After running a release command:

# Push the commit and tag
git push --follow-tags origin main

# The GitHub Action will automatically publish to npm when a tag is pushed

License

This project is licensed under the Apache 2.0.