Skip to content
Open
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
5 changes: 0 additions & 5 deletions .changeset/initial-release.md

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}

Expand Down
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
# venfork

## 0.2.0

### Minor Changes

- [`61a2e54`](https://github.com/cabljac/venfork/commit/61a2e5454dbb04d089898ab2837e0f247954c3f8) Thanks [@cabljac](https://github.com/cabljac)! - Performance improvements and bug fixes:

- **Faster setup**: Changed from full repository mirror to cloning only the default branch, dramatically reducing setup time for large repositories
- **Fixed argument parsing**: Now supports both `--org value` and `--org=value` formats for the organization flag

## 0.1.1

### Patch Changes

- Update README documentation to reflect v0.1.0 changes - update all examples from `-vendor` to `-private` suffix and document new venfork-config branch feature

## 0.1.0

### Minor Changes

- **New Features:**

- Add venfork-config branch for reliable clone detection - stores publicForkUrl and upstreamUrl in `.venfork/config.json` on a dedicated orphan branch
- Clone command now reads config first, falling back to auto-detection if not found

**Improvements:**

- Change default suffix from `-vendor` to `-private` for private mirror repositories
- Fix personal account handling - passing `--org` with your personal username now works correctly
- Improve setup prompts to only ask for missing values instead of always prompting

**Bug Fixes:**

- Fix GitHub API error when using personal account with `--org` flag
- Fix redundant upstream URL prompt when provided as command argument

### Patch Changes

- [`86a246b`](https://github.com/cabljac/venfork/commit/86a246b5bf9c39463854c45d514d3e8edce6df38) Thanks [@cabljac](https://github.com/cabljac)! - Initial release of venfork - Create and manage private mirrors for vendor development workflows. Includes setup, sync, stage, and status commands.

## 0.0.1

### Patch Changes
Expand Down
194 changes: 156 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<p align="center">
<img src="https://raw.githubusercontent.com/cabljac/venfork/refs/heads/main/assets/logo.svg" alt="Venfork Logo" width="200" />
</p>

# 🔧 Venfork

[![CI](https://github.com/cabljac/venfork/actions/workflows/ci.yml/badge.svg)](https://github.com/cabljac/venfork/actions/workflows/ci.yml)
Expand All @@ -9,19 +13,21 @@ Create and manage private mirrors of public GitHub repositories for vendor devel

Venfork helps contractors and vendors who need to work on private forks of public repositories. It creates a **three-repository workflow**:

1. **Private Mirror** (`yourname/project-vendor`) - Where your team works internally
2. **Public Fork** (`yourname/project`) - Staging area for contributions to upstream
1. **Private Mirror** (`yourname/project-private` or `org/project-private`) - Where your team works internally
2. **Public Fork** (`yourname/project` or `org/project`) - Staging area for contributions to upstream
3. **Upstream** (`original/project`) - The original repository

> **Note:** Repos can be created under your personal account or under an organization using the `--org` flag.

### Why Three Repositories?

**The Key Insight:**
> "Because the private fork is not attached to the public repo, our juniors can work on it and learn there without being seen by our client"
> "The private mirror is completely disconnected from the public fork, allowing teams to experiment freely before presenting work to the client"

The private mirror is:
- ✅ Completely disconnected from the public fork
- ✅ Safe for junior devs to learn, make mistakes, iterate
- ✅ All internal PRs, reviews, experiments stay private
- ✅ Safe space to experiment, iterate, and refine work
- ✅ All internal PRs, reviews, and experiments stay private
- ✅ Only visible to your team

When you run `venfork stage`, your work becomes visible on the public fork and ready for PR to upstream.
Expand Down Expand Up @@ -57,14 +63,20 @@ npx venfork setup <repo-url>
## Quick Start

```bash
# 1. One-time setup
# 1a. One-time setup (first team member, personal account)
venfork setup git@github.com:awesome/project.git

cd project-vendor
# Or for organization repos
venfork setup git@github.com:awesome/project.git --org my-company

# 1b. Clone existing setup (other team members)
venfork clone git@github.com:yourname/project-private.git

cd project-private

# 2. Work privately
git checkout -b feature/new-thing
# ... make changes, learn, iterate ...
# ... experiment, iterate, refine ...
git push origin feature/new-thing
# Still private! Create internal PR for team review

Expand All @@ -76,48 +88,102 @@ venfork stage feature/new-thing

## Commands

### `venfork setup <upstream-url> [name]`
### `venfork setup <upstream-url> [name] [--org <organization>]`

Creates the complete vendor workflow setup:

**What it creates:**
- **Private mirror** (`yourname/project-vendor`) - For internal work
- **Public fork** (`yourname/project`) - For staging to upstream
- **Private mirror** (`yourname/project-private` or `org/project-private`) - For internal work
- **Public fork** (`yourname/project` or `org/project`) - For staging to upstream
- **Config branch** (`venfork-config`) - Stores remote URLs for easy team cloning
- **Local clone** with three remotes configured:
- `origin` → private mirror (default push/pull)
- `public` → public fork (for staging)
- `upstream` → original repo (read-only, push disabled)

**Arguments:**
- `upstream-url` - GitHub repository URL (SSH or HTTPS)
- `name` - (Optional) Name for private vendor repo (default: `{repo}-vendor`)
- `name` - (Optional) Name for private mirror repo (default: `{repo}-private`)
- `--org <organization>` - (Optional) Create repos under organization instead of personal account

**Examples:**
```bash
# Personal account (default)
venfork setup git@github.com:vercel/next.js.git
# Creates: next.js-vendor (private), next.js (public fork)
# Creates: yourname/next.js-private (private), yourname/next.js (public fork)

venfork setup https://github.com/vuejs/vue.git vue-internal
# Creates: vue-internal (private), vue (public fork)
# Creates: yourname/vue-internal (private), yourname/vue (public fork)

# Organization account
venfork setup git@github.com:client/awesome-project.git --org acme-corp
# Creates: acme-corp/awesome-project-private (private), acme-corp/awesome-project (public fork)

venfork setup git@github.com:client/project.git internal-mirror --org my-company
# Creates: my-company/internal-mirror (private), my-company/project (public fork)
```

### `venfork clone <vendor-repo-url>`

Clone an existing vendor setup and automatically configure all remotes.

**What it does:**
- Clones the private mirror repository
- **Reads venfork-config branch** for public fork and upstream URLs (if available)
- Falls back to auto-detection:
- Public fork (by stripping `-private` suffix)
- Upstream repository (from public fork's parent)
- Configures all three remotes (origin, public, upstream)
- Disables push to upstream (read-only)

**Use this when:**
- A teammate has already run `venfork setup`
- You need to clone an existing vendor setup
- You want automatic remote configuration

**Arguments:**
- `vendor-repo-url` - GitHub URL of the private vendor repository (SSH or HTTPS)

**Examples:**
```bash
# Clone existing vendor setup (personal account)
venfork clone git@github.com:yourname/project-private.git
# Reads config from venfork-config branch (if available)
# Or auto-detects: public fork at yourname/project

# Clone organization vendor setup
venfork clone git@github.com:acme-corp/awesome-project-private.git
# Reads config from venfork-config branch (if available)
# Or auto-detects: public fork at acme-corp/awesome-project
```

**Interactive prompts:**
- If public fork cannot be auto-detected, you'll be prompted for the URL
- If upstream cannot be auto-detected (no parent), you'll be prompted for the URL

### `venfork sync [branch]`

Fetch from upstream and rebase current branch to stay up-to-date.
Update the default branches of your private mirror and public fork to match upstream.

**Arguments:**
- `branch` - (Optional) Upstream branch to sync with (default: `main`)
- `branch` - (Optional) Upstream branch to sync (default: auto-detected, usually `main` or `master`)

**Examples:**
```bash
venfork sync # Sync with upstream/main
venfork sync develop # Sync with upstream/develop
venfork sync # Sync default branches with upstream
venfork sync develop # Sync develop branch with upstream/develop
```

**What it does:**
1. Fetches latest changes from upstream
2. Rebases your current branch on upstream
3. Handles conflicts gracefully with instructions
1. Fetches latest changes from all remotes (upstream, origin, public)
2. Checks for divergent commits (warns if found to prevent data loss)
3. Force pushes upstream's default branch to origin and public
4. **Does not affect your current working branch or feature branches**

**Important:**
- This keeps your default branches (main/master) in sync with upstream
- Your current work on feature branches is completely unaffected
- If divergent commits are detected, sync will abort to prevent data loss

### `venfork status`

Expand Down Expand Up @@ -161,31 +227,79 @@ venfork stage bugfix/issue-123
3. Pushes to public fork
4. Provides PR creation link

## Environment Variables

### `VENFORK_ORG`

Set a default organization for all venfork commands. This avoids having to type `--org` every time.

**Priority order:**
1. `--org` flag (highest priority - always overrides)
2. `VENFORK_ORG` environment variable
3. Personal account (prompts for confirmation)

**Usage:**

```bash
# Set in your shell profile (~/.zshrc, ~/.bashrc, etc.)
export VENFORK_ORG=my-company

# Now all commands use this org by default
venfork setup git@github.com:client/project.git
# Creates: my-company/project-vendor (private), my-company/project (public fork)

# Override with --org flag when needed
venfork setup git@github.com:other-client/app.git --org different-org
# Creates: different-org/app-vendor (private), different-org/app (public fork)
```

**Safety feature:**
If neither `--org` nor `VENFORK_ORG` is set, venfork will prompt for confirmation before creating repos under your personal account. This prevents accidental personal repo creation when working as a vendor/contractor.

```bash
# Without VENFORK_ORG or --org
venfork setup git@github.com:client/project.git

# Output:
# ⚠️ No organization specified
# Repos will be created under your personal account (username: yourname)
# Continue with personal account? (y/N)
```

## Complete Workflow

### Initial Setup

```bash
# Clone and configure the repos
# Clone and configure the repos (personal account)
venfork setup git@github.com:client/awesome-project.git

# Or for organization
venfork setup git@github.com:client/awesome-project.git --org acme-corp

# Navigate to private mirror
cd awesome-project-vendor
cd awesome-project-private

# Check setup status
venfork status

# Or verify remotes manually
git remote -v
# origin git@github.com:you/awesome-project-vendor.git (private)
# With personal account:
# origin git@github.com:you/awesome-project-private.git (private)
# public git@github.com:you/awesome-project.git (public fork)
# upstream git@github.com:client/awesome-project.git (read-only)

# With organization:
# origin git@github.com:acme-corp/awesome-project-private.git (private)
# public git@github.com:acme-corp/awesome-project.git (public fork)
# upstream git@github.com:client/awesome-project.git (read-only)
```

### Daily Development

```bash
# Sync with upstream before starting
# Sync default branches with upstream (optional, keeps main up-to-date)
venfork sync

# Create feature branch
Expand All @@ -206,7 +320,7 @@ git push origin feature/user-auth

```bash
# Team reviews PR in private repo
# Junior devs iterate, learn, make mistakes
# Experiment, iterate, refine approach
# All feedback and changes stay private

# Once approved internally, merge to main
Expand Down Expand Up @@ -241,7 +355,7 @@ venfork stage feature/user-auth
│ fork
┌─────────────────────────────────────────────┐
│ Public Fork (you/project)
│ Public Fork (you/project or org/project)
│ • Visible to everyone │
│ • Staging area for PRs │
│ • Only pushed to via `venfork stage` │
Expand All @@ -250,11 +364,13 @@ venfork stage feature/user-auth
│ mirror (disconnected)
┌─────────────────────────────────────────────┐
│ Private Mirror (you/project-vendor) │
│ Private Mirror (you/project-private) │
│ (or org/project-private) │
│ • Only visible to your team │
│ • Where juniors learn & iterate
│ • Safe space to experiment & iterate │
│ • Internal PRs and reviews │
│ • Your daily work happens here │
│ • Contains venfork-config branch │
└─────────────────────────────────────────────┘
```

Expand All @@ -266,15 +382,17 @@ After `venfork setup`, your local repository has three remotes:

| Remote | URL | Purpose |
|--------|-----|---------|
| `origin` | `you/project-vendor` | Private work (default) |
| `public` | `you/project` | Stage for upstream |
| `origin` | `you/project-private` (or `org/project-private`) | Private work (default) |
| `public` | `you/project` (or `org/project`) | Stage for upstream |
| `upstream` | `original/project` | Sync with latest |

**Note:** When using `--org`, all repos are created under the specified organization.

### Default Behavior

- `git push` → Pushes to `origin` (private mirror)
- `git pull` → Pulls from `origin` (private mirror)
- `venfork sync` → Fetches from `upstream`
- `venfork sync` → Updates default branches of `origin` and `public` to match `upstream`
- `venfork stage` → Pushes to `public`

## Troubleshooting
Expand All @@ -300,13 +418,13 @@ This means `venfork setup` wasn't run or didn't complete successfully.
- Run `venfork status` to see which remotes are missing
- Re-run `venfork setup` if needed

### Rebase Conflicts
### Divergent Commits Warning

When `venfork sync` encounters conflicts:
1. Open the conflicted files and resolve markers
2. Stage the resolved files: `git add <file>`
3. Continue: `git rebase --continue`
4. Or abort: `git rebase --abort`
If `venfork sync` detects commits on your default branch that aren't in upstream:
1. This suggests work was committed directly to main/master (not recommended)
2. Sync will abort to prevent losing these commits
3. To preserve: manually rebase or cherry-pick them to a feature branch
4. To force sync anyway: `git push origin upstream/main:main -f` (loses commits)

### Branch Already Exists on Public Fork

Expand Down
Loading