A cross-platform Git dependency management tool that automates cloning, checking out, and version-pinning of multiple repositories from a single JSON configuration. Designed for multi-repo projects where teams need reproducible builds without the complexity of git submodules or monorepo tooling.
LsiGitCheckout resolves recursive dependencies across repository trees, supports both Semantic Versioning (SemVer) and tag-based version pinning, and handles SSH authentication (PuTTY on Windows, OpenSSH on macOS/Linux), Git LFS, and post-checkout script execution.
- Features
- Supported Platforms
- Platform Setup
- Installation
- Basic Usage (Non-Recursive)
- Advanced Usage (Recursive Mode)
- Dependency Resolution Modes
- SemVer Mode
- Agnostic Mode
- Choosing Between Dependency Resolution Modes
- Custom Dependency Files
- Post-Checkout Scripts
- Security Best Practices
- SSH Setup
- Troubleshooting
- Version Migration Guide
- Advanced Topics
- License
- Contributing
- Clone and Checkout: Automatically clone and checkout multiple Git repositories to pinned versions from a single JSON configuration
- Version Pinning: Pin repositories to exact tags or SemVer ranges for reproducible builds across your team
- Recursive Dependency Resolution: Discover and resolve nested repository dependencies with API compatibility checking — an alternative to git submodules for multi-repo projects
- Dependency Resolution Modes: Choose between SemVer (Semantic Versioning with floating versions) and Agnostic (explicit tag-based) resolution
- Floating Versions: SemVer floating version patterns (x.y.*, x.*) for automatic latest compatible version selection
- Cross-Platform SSH: PuTTY/Pageant on Windows, OpenSSH on macOS/Linux — automated git authentication per host
- Secure Credentials Management: SSH keys stored separately from repository configuration
- Submodule Support: Handles Git submodules with automatic per-host SSH key lookup
- Git LFS Support: Optional Git LFS content management with skip functionality
- Smart Reset: Automatically resets repositories to clean state before checkout
- Structured JSON Output: Machine-readable results with per-repo status, dependency chains, and error details for CI/CD integration
- Dry Run Mode: Preview clone and checkout operations without making changes
- Flexible Compatibility Modes: Choose between Strict and Permissive API compatibility modes for Agnostic mode
- Custom Dependency Files: Support for different project structures and naming conventions with proper isolation
- Post-Checkout Scripts: Execute PowerShell scripts after successful repository checkouts for integration with external dependency management systems
| Component | Windows 10/11, Server 2016+ | macOS | Linux |
|---|---|---|---|
| PowerShell | 7.6 LTS (side-by-side with 5.1) | 7.6 LTS | 7.6 LTS |
| Git | Git for Windows 2.x+ | Xcode CLI tools or standalone | Distribution package |
| SSH transport | PuTTY/plink + Pageant (.ppk keys) |
OpenSSH (bundled) | OpenSSH (bundled) |
| HTTPS auth | Git Credential Manager (bundled with Git for Windows) | Git Credential Manager | Git Credential Manager or PAT |
| Git LFS | Optional | Optional | Optional |
-
Install PowerShell 7.6 LTS (installs as
pwsh.exealongside Windows PowerShell 5.1 — existing scripts are unaffected):winget install Microsoft.PowerShell
-
Install Git for Windows (includes Git Credential Manager for HTTPS authentication):
Download from git-scm.com or:
winget install Git.Git
-
Set execution policy (one-time, allows running local scripts):
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
-
SSH setup (only if accessing repositories via SSH URLs):
LsiGitCheckout uses PuTTY/plink on Windows. See SSH Setup.
-
Install PowerShell 7.6 LTS:
# Via Homebrew (recommended) brew install powershell # Or via .NET global tool dotnet tool install --global PowerShell
-
Install Git (may already be installed via Xcode CLI tools):
# Check if installed git --version # Install Xcode CLI tools if needed xcode-select --install
-
Install Git Credential Manager (for HTTPS authentication to GitHub, Azure DevOps, etc.):
brew install git-credential-manager git-credential-manager configure
-
SSH setup (only if accessing repositories via SSH URLs):
macOS includes OpenSSH. See SSH Setup.
-
Install PowerShell 7.6 LTS:
# Ubuntu/Debian sudo apt-get update sudo apt-get install -y powershell # RHEL/CentOS/Fedora sudo dnf install powershell # Or via .NET global tool dotnet tool install --global PowerShell
See Microsoft's Linux installation guide for all distributions.
-
Install Git:
# Ubuntu/Debian sudo apt-get install git # RHEL/CentOS/Fedora sudo dnf install git
-
Install Git Credential Manager (for HTTPS authentication):
# Download latest .deb or .rpm from: # https://github.com/git-credential-manager/git-credential-manager/releases sudo dpkg -i gcm-linux_amd64.deb # Debian/Ubuntu git-credential-manager configure
Alternatively, use a Personal Access Token (PAT) for HTTPS repos.
-
SSH setup (only if accessing repositories via SSH URLs):
Linux includes OpenSSH. See SSH Setup.
-
Download
LsiGitCheckout.ps1,LsiGitCheckout.psm1, andLsiGitCheckout.psd1to the same directory -
Create
dependencies.jsonwith your repository configuration -
Create
git_credentials.jsonwith your SSH key mappings (if using SSH repositories) -
Run with
pwsh:pwsh ./LsiGitCheckout.ps1 -InputFile dependencies.json
In non-recursive mode, the script processes only the repositories listed in your main dependencies file. It does not look for or process any nested dependencies.
# Use default settings (recursive mode and intelligent tag sorting enabled by default)
.\LsiGitCheckout.ps1
# Specify custom JSON files
.\LsiGitCheckout.ps1 -InputFile "C:\configs\myrepos.json" -CredentialsFile "C:\configs\my_credentials.json"
# Enable debug logging
.\LsiGitCheckout.ps1 -EnableDebug
# Dry run mode (preview without changes)
.\LsiGitCheckout.ps1 -DryRun
# Verbose output
.\LsiGitCheckout.ps1 -Verbose
# Set default API compatibility mode (applies only to Agnostic mode repositories)
.\LsiGitCheckout.ps1 -ApiCompatibility Strict
# Disable recursive mode (non-recursive mode)
.\LsiGitCheckout.ps1 -DisableRecursion
# Disable post-checkout script execution
.\LsiGitCheckout.ps1 -DisablePostCheckoutScripts
# Enable detailed error context for debugging
.\LsiGitCheckout.ps1 -EnableErrorContext
# Export structured JSON results for CI/CD pipelines
.\LsiGitCheckout.ps1 -OutputFile result.json-InputFile: Path to repository configuration file (default: dependencies.json)-CredentialsFile: Path to SSH credentials file (default: git_credentials.json)-DryRun: Preview operations without making changes-EnableDebug: Create detailed debug log file-Verbose: Show verbose output messages-ApiCompatibility: Default API compatibility mode for Agnostic mode repositories ('Strict' or 'Permissive', default: 'Permissive')-DisableRecursion: Disable recursive dependency processing (default: recursive mode enabled)-DisablePostCheckoutScripts: Disable post-checkout script execution (default: post-checkout scripts enabled)-EnableErrorContext: Enable detailed error context with stack traces (default: simple errors only)-OutputFile: Write structured JSON results to the specified file path (for CI/CD integration)
When -OutputFile is specified, a JSON file is written with the results of the checkout operation. The output is guaranteed to be written even on failure, making it safe for CI/CD pipelines. Schema version: 1.0.0.
.\LsiGitCheckout.ps1 -InputFile deps.json -OutputFile result.jsonOutput structure:
| Field | Type | Description |
|---|---|---|
schemaVersion |
string | JSON schema version ("1.0.0") |
metadata |
object | Execution context: toolVersion, timestamp, dryRun, recursiveMode, maxDepth, apiCompatibility, inputFile, powershellVersion |
summary |
object | success (bool), successCount, failureCount, totalRepositories, postCheckoutScripts (enabled/executions/failures) |
repositories[] |
array | Per-repository results (see below) |
processedDependencyFiles[] |
array | Absolute paths of all dependency files processed |
rootPostCheckoutScripts[] |
array | Post-checkout script tracking for depth-0 (root-level) scripts |
errors[] |
array | Error messages collected during execution |
Repository entry fields:
| Field | Type | Description |
|---|---|---|
url |
string | Repository URL |
path |
string | Absolute checkout path |
dependencyResolution |
string | "SemVer" or "Agnostic" |
status |
string | "success", "failed", or "skipped" |
alreadyCheckedOut |
bool | Whether the repo was already at the correct version |
requestedBy |
string[] | Parent repo URLs or "root-dependency-file" |
tag |
string | Git tag checked out |
requestedVersion |
string? | SemVer version pattern requested (SemVer only) |
selectedVersion |
string? | SemVer version selected (SemVer only) |
postCheckoutScript |
object? | Script tracking: configured, scriptPath, found, executed, status, reason (null if no script configured) |
Post-checkout script status values: "executed", "failed", "skipped", "timeout"
LsiGitCheckout provides two approaches for determining which git tag to checkout for each repository. Both modes examine the available git tags in each repository to make their selection decisions.
Uses Semantic Versioning 2.0.0 rules with the Version field in your dependency file to automatically determine compatible tags.
How it works:
- You specify a
"Version"field in your dependency file for each repository - Script fetches all git tags from the repository
- Parses tags using a version regex pattern to extract semantic versions
- Finds all tags compatible with your version requirement
- Selects the appropriate version based on your pattern type
Version Field Patterns in Dependency File:
- Lowest Applicable (
x.y.z): Selects minimum version that satisfies compatibility- Example:
"Version": "2.1.0"in dependency file → Selects 2.1.0, 2.1.1, or 2.2.0 but not 3.0.0
- Example:
- Floating Patch (
x.y.*): Automatically selects latest patch within major.minor- Example:
"Version": "2.1.*"in dependency file → Selects latest 2.1.x (e.g., 2.1.5 if available)
- Example:
- Floating Minor (
x.*): Automatically selects latest minor.patch within major- Example:
"Version": "2.*"in dependency file → Selects latest 2.x.x (e.g., 2.5.3 if available)
- Example:
Key Benefits:
- Zero maintenance for compatible updates
- Automatic selection of bug fixes and compatible features
- Clear boundaries preventing breaking changes
Uses explicit tag specification with the Tag field in your dependency file to checkout exact versions.
How it works:
- You specify a
"Tag"field in your dependency file for each repository - Script checks if the specified tag exists in the repository
- Checks out exactly the requested tag
- No automatic version resolution or compatibility checking
Tag Field Usage in Dependency File:
- Exact Tag (
Tag): Specifies the precise git tag to checkout- Example:
"Tag": "v2.1.0"in dependency file → Checks out exactly tag v2.1.0
- Example:
Key Benefits:
- Maximum control over exact versions
- Works with any tagging scheme
- Explicit, predictable behavior
The dependencies.json file contains the specification of the repositories that are your dependencies. This file lists all the repositories you want to checkout and configure, without any credential information:
SemVer Mode Configuration (Recommended):
{
"Post-Checkout Script File Name": "setup-dependencies.ps1",
"Post-Checkout Script File Path": "scripts/build",
"Repositories": [
{
"Repository URL": "https://github.com/user/repo.git",
"Base Path": "repos/my-repo",
"Dependency Resolution": "SemVer",
"Version": "2.1.*",
"Version Regex": "^v(\\d+)\\.(\\d+)\\.(\\d+)$",
"Skip LFS": false
}
]
}Agnostic Mode Configuration:
{
"Repositories": [
{
"Repository URL": "https://github.com/user/repo.git",
"Base Path": "repos/my-repo",
"Tag": "v2.1.0",
"Skip LFS": false
}
]
}Simple Array Format (Legacy Support):
[
{
"Repository URL": "https://github.com/user/repo.git",
"Base Path": "repos/my-repo",
"Dependency Resolution": "SemVer",
"Version": "2.*"
}
]Common Fields:
- Repository URL (required): Git repository URL (HTTPS or SSH)
- Base Path (required): Local directory checkout path (relative or absolute)
- Dependency Resolution (optional): "SemVer" (recommended) or "Agnostic" (default)
- Skip LFS (optional): Skip Git LFS downloads for this repository
- Dependency File Path (optional): Custom subdirectory for dependency file
- Dependency File Name (optional): Custom name for dependency file
SemVer Mode Fields:
- Version (required): Semantic version requirement (e.g., "2.1.0", "2.1.", "2.")
- Version Regex (optional): Custom regex pattern for version extraction from tags (default:
^v?(\\d+)\\.(\\d+)\\.(\\d+)$)
Agnostic Mode Fields:
- Tag (required): Git tag to checkout (e.g., "v2.1.0")
Post-Checkout Script Fields:
- Post-Checkout Script File Name (optional): PowerShell script to execute after checkout
- Post-Checkout Script File Path (optional): Subdirectory where script is located
Maps hostnames to SSH key file paths. The key format depends on your platform:
Windows (PuTTY .ppk format):
{
"github.com": "C:\\Users\\username\\.ssh\\github_key.ppk",
"gitlab.com": "C:\\Users\\username\\.ssh\\gitlab_key.ppk",
"ssh://git.internal.corp": "C:\\keys\\internal_key.ppk"
}macOS/Linux (OpenSSH format):
{
"github.com": "/home/username/.ssh/id_ed25519",
"gitlab.com": "/home/username/.ssh/gitlab_rsa",
"ssh://git.internal.corp": "/home/username/.ssh/internal_key"
}[
{
"Repository URL": "https://github.com/microsoft/terminal.git",
"Base Path": "repos/windows-terminal",
"Dependency Resolution": "SemVer",
"Version": "1.19.*"
},
{
"Repository URL": "https://github.com/PowerShell/PowerShell.git",
"Base Path": "repos/powershell",
"Dependency Resolution": "SemVer",
"Version": "7.*",
"Skip LFS": true
}
][
{
"Repository URL": "https://github.com/microsoft/terminal.git",
"Base Path": "repos/windows-terminal",
"Tag": "v1.19.10573.0"
},
{
"Repository URL": "https://github.com/PowerShell/PowerShell.git",
"Base Path": "repos/powershell",
"Tag": "v7.4.1",
"Skip LFS": true
}
][
{
"Repository URL": "https://github.com/org/modern-lib.git",
"Base Path": "libs/modern",
"Dependency Resolution": "SemVer",
"Version": "3.*"
},
{
"Repository URL": "https://github.com/org/legacy-lib.git",
"Base Path": "libs/legacy",
"Tag": "release-2024-01"
}
]When Recursive Mode is enabled (Default) the script automatically discovers and processes nested dependencies. After checking out each repository, it looks for a dependency file (dependencies.json if not specified differently upon script execution) within the root folder of that repository and processes it recursively, with intelligent handling of shared dependencies.
# Default behavior (recursive mode enabled with intelligent tag sorting)
.\LsiGitCheckout.ps1
# Disable recursive mode for simple single-file processing
.\LsiGitCheckout.ps1 -DisableRecursion
# Customize recursive behavior
.\LsiGitCheckout.ps1 -MaxDepth 10
# Use strict compatibility mode for Agnostic mode repositories
.\LsiGitCheckout.ps1 -ApiCompatibility Strict
# Disable post-checkout scripts
.\LsiGitCheckout.ps1 -DisablePostCheckoutScriptsWhen recursive mode processes nested dependencies, a common scenario emerges: the same repository is required by multiple projects with potentially different version requirements. This creates the fundamental challenge that the script's dependency resolution system is designed to solve.
Consider this scenario:
- ProjectA requires
LibraryXat versionv2.1.0(or2.1.*in SemVer mode) - ProjectB also requires
LibraryXbut at versionv2.0.5(or2.0.*in SemVer mode) - Both projects expect to work with
LibraryX, but they're requesting different versions
When the script encounters LibraryX for the second time, it faces a critical decision: which version should be checked out to satisfy both callers?
Main Project Dependencies:
├── ProjectA (requires LibraryX v2.1.0 or 2.1.*)
└── ProjectB (requires LibraryX v2.0.5 or 2.0.*)
When processing recursively:
- Round 1: Processes main dependencies → clones ProjectA and ProjectB
- Round 2:
- Processes ProjectA's dependencies → clones LibraryX at appropriate version
- Processes ProjectB's dependencies → discovers LibraryX already exists!
At this point, the script must determine:
- Are the versions compatible?
- If compatible, which version should be used?
- How do we ensure both ProjectA and ProjectB continue to work?
LsiGitCheckout provides two powerful approaches to solve the dependency resolution problem:
- SemVer Mode: Automatically resolves compatible versions based on Semantic Versioning 2.0.0 rules with floating version support
- Agnostic Mode: Uses explicit "API Compatible Tags" lists with intelligent intersection/union algorithms
Both modes use sophisticated conflict resolution algorithms that consider the compatibility requirements of all callers and select the optimal version that satisfies everyone's needs.
The two dependency resolution modes can be mixed within the same dependency tree.
For detailed documentation on each mode, see:
- SemVer Mode -- Automatic version resolution using Semantic Versioning 2.0.0 rules with floating version patterns for zero-maintenance dependency updates.
- Agnostic Mode -- Tag-based resolution using explicit API Compatible Tags lists for maximum control over version compatibility.
- Choosing Between Modes -- Guidance on when to use each mode, with best practices for mixed-mode dependency trees.
Per-repository custom dependency file paths and names provide flexibility for different project structures and naming conventions. For details, see Custom Dependency Files.
Post-checkout scripts are PowerShell scripts that execute automatically after a repository is successfully checked out, enabling integration with external dependency management systems. For details, see Post-Checkout Scripts.
Guidelines for protecting credentials, SSH keys, and managing post-checkout script security. For details, see Security Best Practices.
Platform-specific SSH configuration for Windows (PuTTY/Pageant) and macOS/Linux (OpenSSH). For details, see SSH Setup.
Common issues and solutions, debug mode instructions, and enhanced error context. For details, see Troubleshooting.
Step-by-step instructions for upgrading between LsiGitCheckout versions (6.2.x to 7.0.0, 7.0.0 to 7.1.0). For details, see Version Migration Guide.
Links to in-depth guides on migrating dependency trees to LsiGitCheckout and tool comparisons. For details, see Advanced Topics.
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
Originally developed by LS Instruments AG for managing complex multi-repository projects.
Co-authored with Claude (Anthropic) through collaborative development.