Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
The MIT License (MIT)

Copyright © 2025 Jad Bitar
Copyright © 2026 Idea Crafters LLC
Copyright © 2026 Jad Bitar

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
230 changes: 103 additions & 127 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
> force-pushed and rewritten** multiple times. Do not fork, clone, or
> depend on this repo in any capacity until we tag a stable release.

A Git subcommand that wraps `git worktree` with deterministic, isolated, and reproducible multi-branch development environments.

## Overview

git-hop eliminates the friction of managing multiple Git worktrees by automatically organizing worktrees, allocating resources (ports, volumes, networks), and providing lifecycle management for Docker environments. Work on multiple branches in parallel without port conflicts, manual configuration, or lost context.
Work on multiple branches in parallel without manual port setup, directory management, or lost context. Each branch gets its own isolated environment with deterministic ports and volumes.

**Perfect for:**
- Multi-branch development workflows
Expand All @@ -27,15 +23,6 @@ git-hop eliminates the friction of managing multiple Git worktrees by automatica
- Multi-tenant setups
- Monorepo optimization (see Git's native monorepo support)

## Features

- 🚀 **Automatic Navigation** - Optional shell integration for seamless worktree switching
- 🔗 **Smart Symlinks** - `current` symlink always points to your last worktree
- 🐳 **Docker Integration** - Isolated environments with deterministic port allocation
- 📦 **Dependency Management** - Automatic npm/yarn/pnpm installation per worktree
- 🔄 **State Tracking** - Track all worktrees across your system
- 🛠️ **Zero Config** - Sensible defaults, works out of the box

## Quick Start

### Install
Expand Down Expand Up @@ -82,6 +69,12 @@ git hop add feature-x
cd feature-x
```

**Verify:** Confirm setup succeeded:
```bash
git hop list # See all worktrees
pwd # Should show .../feature-x
```

**Optional:** Install shell integration for automatic directory switching:

```bash
Expand Down Expand Up @@ -121,6 +114,7 @@ git hop env stop
| `git hop status` | Show status of current worktree or hub |
| `git hop remove <target>` | Remove a worktree, hopspace, or hub |
| `git hop prune` | Clean up orphaned worktrees and hubs |
| `git hop repair` | Repair a corrupted or stale worktree |
| `git hop doctor` | Check and repair environment issues |

### Shell Integration (Optional)
Expand All @@ -144,114 +138,6 @@ git hop env start # Start Docker services for current worktree
git hop env stop # Stop Docker services
```

### Global Flags

Available on all commands:

```bash
--config <path> # Path to config file
--json # Output in JSON format
--porcelain # Machine-readable output
--quiet, -q # Suppress output
--verbose, -v # Verbose output
--force # Bypass safety checks
--dry-run # Preview changes without applying
--global, -g # Use global hopspace instead of local
--git-domain <domain> # Git domain for shorthand notation (default: github.com)
--help, -h # Show command help
--version # Show version information
```

## Architecture

### Hubs

A **hub** is a directory that serves as your local working context. It contains:
- A `hop.json` configuration file tracking all worktrees
- A `.git` reference to the bare repository
- Direct access to worktrees via paths stored in config

```
my-repo/ # Hub directory (local context)
.git # Bare repository reference
hop.json # Hub configuration (tracks worktree paths)
```

The hub's `hop.json` maintains references to all worktrees with their full paths, allowing you to quickly switch between branches without manual path management.

### Hopspaces

A **hopspace** is the canonical storage location for all worktrees of a repository. Located at:

```
$GIT_HOP_DATA_HOME/<domain>/<org>/<repo>/
hop.json # Hopspace configuration
ports.json # Port allocations
volumes.json # Volume allocations
feature-x/ # Actual worktree directory
feature-y/
...
```

All worktrees for a repository reference the same hopspace, ensuring consistency.

### Deterministic Resource Allocation

Ports, volumes, and networks are derived from stable hashing:

- **Same branch = same ports** across worktrees (reproducible)
- **Different branches = different ports** (no conflicts)
- **Predictable allocation** (no manual configuration)

Example: branch `feature-x` always gets ports 11500-11505 if not already assigned.

## Configuration

Configuration follows a hierarchy (higher priority overrides lower):

1. Environment variables
2. Command-line flags
3. `$XDG_CONFIG_HOME/git-hop/config.json` (global)
4. Hub-level `hop.json`
5. Hopspace-level `hop.json`

### Configuration File

Create `$XDG_CONFIG_HOME/git-hop/config.json`:

```json
{
"auto_env_start": "detect",
"port_base": 10000,
"port_limit": 5000,
"defaults": {
"worktree_location": "hops"
}
}
```

Configuration options:

- `auto_env_start` - Auto-start Docker services (`true`, `false`, or `"detect"` to start only if services exist)
- `port_base` - Starting port for allocation (default: 10000)
- `port_limit` - Maximum ports available (default: 5000)
- `defaults.worktree_location` - Directory for storing worktrees (default: `hops`)

### Environment Variables

```bash
GIT_HOP_DATA_HOME # Hopspace storage location (OS-specific default)
GIT_HOP_CONFIG_HOME # Config directory (default: $XDG_CONFIG_HOME/git-hop)
GIT_HOP_CACHE_DIR # Cache directory (default: $XDG_CACHE_HOME/git-hop)
GIT_HOP_LOG_LEVEL # Log level: debug, info, warn, error (default: info)
```

### Data Directory Defaults

- **Linux/Unix**: `~/.local/share/git-hop`
- **macOS**: `~/Library/Application Support/git-hop`
- **Windows**: `%LOCALAPPDATA%\git-hop`

## Common Workflows

### Add a New Feature Branch
Expand All @@ -264,6 +150,12 @@ git hop add feature-new-ui
cd feature-new-ui
```

**Verify:** Confirm the worktree was created:
```bash
git hop list # See feature-new-ui in the list
pwd # Should show .../feature-new-ui
```

### Switch Between Branches

```bash
Expand All @@ -276,6 +168,11 @@ cd ../feature-existing
# Or use your shell navigation (e.g., cd /path/to/hop/feature-existing)
```

**Verify:** Confirm you're in the right worktree:
```bash
git branch # Should show the feature branch checked out
```

### Start/Stop Services

```bash
Expand All @@ -284,8 +181,16 @@ git hop env start

# Stop services
git hop env stop
```

# Auto-start on worktree creation
**Verify:** Check service status:
```bash
git hop status # Shows running services
docker ps # Verify containers are running
```

To auto-start services on worktree creation:
```bash
git hop config auto_env_start detect
```

Expand Down Expand Up @@ -320,6 +225,24 @@ git hop prune
git hop doctor --fix
```

## Configuration

For detailed configuration, see [Configuration Guide](docs/configuration.md).

Quick setup:

```bash
git hop config --help # View all settings
git hop config port_base 20000 # Change port base
Comment on lines 227 to +236
```

Configuration hierarchy (first found wins):
1. Environment variables
2. Hub-level `hop.json`
3. Hopspace-level `hop.json`
4. Global `~/.config/git-hop/config.json`
5. Built-in defaults

## Troubleshooting

### Port Conflicts
Expand Down Expand Up @@ -405,7 +328,60 @@ Place hooks in `$GIT_HOP_CONFIG_HOME/hooks/` or hopspace-specific directories to

See [Hooks System](docs/hooks.md) for detailed examples.

## Output Formats
## Advanced: How It Works

### How git-hop Organizes Your Work

Git-hop keeps your branches isolated across two layers:

**Hub** — the directory where you run `git hop` commands. Usually `~/my-repo/`. Tells git-hop which branches exist locally. Contains `hop.json` and a `.git` reference.

**Hopspace** — centralized storage for all branches of a repository, shared by all hubs. Located at `$GIT_HOP_DATA_HOME/<org>/<repo>/`. Contains actual worktree directories, port allocations, and volume mappings.

Why two? Hubs are your local workspace; hopspace is shared storage. This lets you have multiple hubs (checkouts) of the same repository, all using the same branches without duplication.

### Hubs

A **hub** is a directory that serves as your local working context. It contains:
- A `hop.json` configuration file tracking all worktrees
- A `.git` reference to the bare repository
- Direct access to worktrees via paths stored in config

```
my-repo/ # Hub directory (local context)
.git # Bare repository reference
hop.json # Hub configuration (tracks worktree paths)
```

The hub's `hop.json` maintains references to all worktrees with their full paths, allowing you to quickly switch between branches without manual path management.

### Hopspaces

A **hopspace** is the canonical storage location for all worktrees of a repository. Located at:

```
$GIT_HOP_DATA_HOME/<domain>/<org>/<repo>/
hop.json # Hopspace configuration
ports.json # Port allocations
volumes.json # Volume allocations
feature-x/ # Actual worktree directory
feature-y/
...
```

All worktrees for a repository reference the same hopspace, ensuring consistency.

### Deterministic Resource Allocation

Ports, volumes, and networks are derived from stable hashing:

- **Same branch = same ports** across worktrees (reproducible)
- **Different branches = different ports** (no conflicts)
- **Predictable allocation** (no manual configuration)

Example: branch `feature-x` always gets ports 11500-11505 if not already assigned.

### Output Formats

Control output with flags:

Expand All @@ -423,9 +399,9 @@ git hop list --porcelain
git hop status --quiet
```

## Configuration Examples
### Configuration Examples

### Multi-Repository Setup
#### Multi-Repository Setup

Manage multiple repositories with different configurations:

Expand All @@ -444,7 +420,7 @@ git hop config port_base 20000

Each repository has its own hopspace with independent resource allocation.

### Docker with Custom Services
#### Docker with Custom Services

Repositories with docker-compose.yml automatically detect and allocate resources:

Expand Down
2 changes: 1 addition & 1 deletion cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ var addCmd = &cobra.Command{

// Create Worktree in the current hub
wm := hop.NewWorktreeManager(fs, g)
worktreePath, err = wm.CreateWorktreeTransactional(hopspace, hubPath, branch, globalConfig.Defaults.WorktreeLocation, hub.Config.Repo.Org, hub.Config.Repo.Repo)
worktreePath, err = wm.CreateWorktreeTransactional(hopspace, hubPath, branch, globalConfig.Defaults.WorktreeLocation, hub.Config.Repo.Org, hub.Config.Repo.Repo, hub.Config.Repo.DefaultBranch)
if err != nil {
// Check if it's a state error
if stateErr, ok := err.(*hop.StateError); ok {
Expand Down
2 changes: 1 addition & 1 deletion cmd/doctor.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ Use --fix to automatically repair issues.`,

// Recreate the worktree using git
g := git.New()
if err := g.CreateWorktree(hopspacePath, b.HopspaceBranch, linkPath, "", false); err != nil {
if err := g.CreateWorktree(hopspacePath, b.HopspaceBranch, linkPath, "", false, "origin/"+b.HopspaceBranch); err != nil {
output.Error("Failed to recreate worktree: %v", err)
continue
}
Expand Down
Loading
Loading