gitrub 1.1.13

A local git server — push, pull, clone over HTTP and SSH with LFS, hooks, and more
Documentation
# gitrub

Local GitHub replacement. Push, pull, clone over HTTP and SSH. Supports LFS, shallow/partial clones, protocol v2, server-side hooks, and archive downloads.

![gitrub demo](https://i.imgur.com/Lc1otpH.gif)

## Install

```
cargo install gitrub
```

Or build from source:

```
cargo build --release
```

## Run

```
gitrub [OPTIONS]

Options:
  --root <DIR>       Repository root (default: ./repos)
  --host <ADDR>      Bind address (default: 0.0.0.0)
  --port <PORT>      HTTP port (default: 3000)
  --ssh-port <PORT>  SSH port (default: 2222)
  --user <USER>      Username for auth
  --pass <PASS>      Password for auth
  --noauth           Skip auth
  --hooks-dir <DIR>  Copy hooks into new repos
  --no-ssh           Disable SSH server
  --recursive        List repos recursively (include nested paths)
```

## Examples

```bash
# No auth, defaults
gitrub --noauth

# With auth
gitrub --user admin --pass secret

# Custom ports + hooks
gitrub --noauth --port 8080 --ssh-port 2222 --hooks-dir ./my-hooks
```

## Usage

```bash
# HTTP
git clone http://localhost:3000/user/project.git
git clone http://admin:secret@localhost:3000/user/project.git

# SSH
git clone ssh://git@localhost:2222/user/project.git

# Shallow clone
git clone --depth 1 http://localhost:3000/user/project.git

# Partial clone (blobless)
git clone --filter=blob:none http://localhost:3000/user/project.git

# Download archive
curl -O http://localhost:3000/user/project.git/archive/main.tar.gz
curl -O http://localhost:3000/user/project.git/archive/v1.0.zip

# Switch from GitHub (replace origin)
git remote set-url origin http://localhost:3000/user/project.git

# Keep GitHub as primary, add gitrub as secondary
git remote add local http://localhost:3000/user/project.git
git push local main

# Push to both at once
git remote set-url --add --push origin git@github.com:user/project.git
git remote set-url --add --push origin http://localhost:3000/user/project.git
git push origin main   # pushes to GitHub AND gitrub
```

Repos auto-create on first push. Any path depth works.

## Using alongside GitHub

Most users keep GitHub as their primary remote. Here's how to add gitrub as a secondary backup or local mirror:

### Option 1: Separate remote (recommended)

Add gitrub as a named remote alongside `origin`:

```bash
# Your repo already has GitHub as origin
git remote -v
# origin  git@github.com:user/project.git (fetch)
# origin  git@github.com:user/project.git (push)

# Add gitrub as a second remote called "local"
git remote add local http://localhost:3000/user/project.git

# Push to gitrub
git push local main

# Push all branches + tags
git push local --all
git push local --tags

# Pull still defaults to GitHub
git pull                 # pulls from origin (GitHub)
git pull local main      # pulls from gitrub
```

### Option 2: Push to both at once

Configure `origin` to push to GitHub **and** gitrub simultaneously:

```bash
# Add gitrub as an additional push URL on origin
git remote set-url --add --push origin git@github.com:user/project.git
git remote set-url --add --push origin http://localhost:3000/user/project.git

# Now every push goes to both
git push origin main     # pushes to GitHub AND gitrub

# Verify
git remote -v
# origin  git@github.com:user/project.git (fetch)
# origin  git@github.com:user/project.git (push)
# origin  http://localhost:3000/user/project.git (push)
```

> **Note:** Fetch still pulls from GitHub only. This is usually what you want — GitHub is the source of truth, gitrub is a local backup.

### Mirror an existing GitHub repo

```bash
# Clone from GitHub, then push everything to gitrub
git clone --mirror git@github.com:user/project.git
cd project.git
git push --mirror http://localhost:3000/user/project.git
```

## Features

| Feature | Status |
|---------|--------|
| Push / Pull / Clone | ✅ HTTP + SSH |
| Branches & Tags ||
| Force push / Delete branch ||
| Git Protocol v2 ||
| Shallow clones (`--depth`) ||
| Partial clones (`--filter`) ||
| Git LFS | ✅ Batch API + basic transfer |
| SSH transport | ✅ Built-in server (Ed25519) |
| Archive download | ✅ tar, tar.gz, zip |
| Server-side hooks |`--hooks-dir` |
| HTTP Basic auth ||
| Auto-create repos on push ||
| Nested paths (`org/team/repo`) ||
| Activity tracking | ✅ Last push/pull timestamps |
| Repo detail view | ✅ Commits, files, branches |
| Recursive repo listing |`--recursive` flag |

## TUI Keybindings

| Key | Action |
|-----|--------|
| ``/`` | Navigate repos or settings |
| `Tab` | Switch focus (settings ↔ repos) |
| `Enter` | Open repo detail view / edit setting |
| `c` | Open command palette for selected repo |
| `/` | Search / filter repos |
| `s` | Start / stop server |
| `r` | Refresh repo list |
| `q` | Quit |

### Repo Detail View

| Key | Action |
|-----|--------|
| `Tab` | Switch tab (Commits → Files → Branches) |
| ``/`` | Scroll |
| `PgUp`/`PgDn` | Scroll by page |
| `c` | Open command palette |
| `r` | Refresh detail data |
| `Esc` | Close detail view |

## Server-side hooks

Create a hooks directory with executable scripts:

```bash
mkdir hooks
cat > hooks/post-receive << 'EOF'
#!/bin/sh
echo "Push received!"
EOF
chmod +x hooks/post-receive

gitrub --noauth --hooks-dir ./hooks
```

Hooks are copied into each new repo's `hooks/` directory. Supported hooks: `pre-receive`, `post-receive`, `update`, and any other git hook.

## LFS

gitrub implements the [Git LFS Batch API](https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md). Configure your repo to use it:

```bash
cd my-project
git lfs install
git lfs track "*.bin"
git add .gitattributes
git commit -m "track binaries with LFS"
git push
```

LFS objects are stored under `<root>/<repo>/lfs/objects/`.

## Test

```
cargo test
```

28 integration tests covering push, pull, clone, branches, tags, force push, branch deletion, auth, shallow clones, partial clones, protocol v2, archive, hooks, and LFS.

## Author

[Eugene Hauptmann](https://github.com/eugenehp)

## License

MIT — see [LICENSE](LICENSE) for details.