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
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ https://github.com/user-attachments/assets/88eb4aed-c00d-4238-b1a9-bcaa34c975c3
# From within a git repository
par start feature-auth # Creates worktree, branch, and tmux session
par start feature-auth --base develop
par start feature-auth --pull-default # Pull default branch first

# From anywhere on your system
par start bugfix-login --path /path/to/repo
Expand Down Expand Up @@ -60,6 +61,7 @@ par control-center # View ALL sessions and workspaces globally with separ

```bash
par workspace start feature-auth --repos frontend,backend
par workspace start feature-auth --repos frontend,backend --pull-default # Pull default branch first
par workspace code feature-auth # Open in VSCode with multi-repo support
par workspace open feature-auth # Attach to unified tmux session
```
Expand Down Expand Up @@ -134,6 +136,7 @@ Create a new isolated development environment:
# From within a git repository
par start my-feature
par start my-feature --base develop
par start my-feature --pull-default

# From anywhere, specifying the repository path
par start my-feature --path /path/to/your/git/repo
Expand All @@ -142,6 +145,8 @@ par start my-feature -p ~/projects/my-app

By default, `par start` branches from the current `HEAD` commit. Use `--base` to branch from a specific branch/reference. `par` resolves the base to a commit SHA, so uncommitted changes in your current worktree do not affect the new branch.

Use `--pull-default` to pull the repository's default branch (determined via `origin/HEAD`) before creating the worktree branch. If no `--base` is provided, the new branch will be based on the freshly pulled default branch. If both `--pull-default` and `--base` are provided, the default branch is still pulled but `--base` takes precedence for the branch point.

If the label already matches an existing local branch, `par start <label>` will reuse that branch and create a worktree with it checked out instead of creating a new branch.
If no local branch exists but `origin/<label>` exists, `par` fetches it and creates the worktree from `origin/<label>`.

Expand Down Expand Up @@ -325,7 +330,7 @@ par workspace cursor feature-auth # Cursor
**Create a workspace:**

```bash
par workspace start <label> [--path /workspace/root] [--repos repo1,repo2] [--open]
par workspace start <label> [--path /workspace/root] [--repos repo1,repo2] [--open] [--pull-default]
```

**List workspaces (now unified with sessions):**
Expand Down Expand Up @@ -534,6 +539,28 @@ Workspaces create branches from the **currently checked out branch** in each rep
- **Different base branches**: Each repo can be on different branches before workspace creation
- **Flexible workflows**: Supports GitFlow, GitHub Flow, or custom branching strategies

**Keeping branches up-to-date with `--pull-default`:**

Use the `--pull-default` flag to automatically pull each repository's default branch (determined via `origin/HEAD`) before creating workspace branches:

```bash
# Single-repo session
par start feature-auth --pull-default

# Multi-repo workspace
par workspace start feature-auth --repos frontend,backend --pull-default
```

This will:
1. Determine each repo's default branch (e.g. `main`) via `origin/HEAD`
2. Checkout that branch in each repo
3. Run `git pull --ff-only` to update it
4. Create workspace branches from the updated default branch

This ensures your workspace branches are always based on the latest upstream code, removing the need to manually checkout and pull each repo beforehand.

> **Note**: If `origin/HEAD` is not set for a repository, run `git remote set-head origin --auto` in that repo first. The pull uses `--ff-only` for safety — if a non-fast-forward update is needed, the operation will fail with a clear error.

## Advanced Usage

### Globally Unique Sessions
Expand Down
38 changes: 31 additions & 7 deletions par/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ def start(
path: Annotated[
Optional[str],
typer.Option(
"--path", "-p",
help="Path to git repository (defaults to current directory)"
"--path",
"-p",
help="Path to git repository (defaults to current directory)",
),
] = None,
base_branch: Annotated[
Expand All @@ -81,6 +82,13 @@ def start(
"--open", help="Automatically open/attach to the session after creation."
),
] = False,
pull_default: Annotated[
bool,
typer.Option(
"--pull-default",
help="Pull the default branch (via origin/HEAD) before creating the worktree branch",
),
] = False,
):
"""
Start a new git worktree and tmux session.
Expand All @@ -93,6 +101,7 @@ def start(
repo_path=path,
open_session=open_session,
base_branch=base_branch,
pull_default=pull_default,
)


Expand Down Expand Up @@ -166,8 +175,9 @@ def checkout(
path: Annotated[
Optional[str],
typer.Option(
"--path", "-p",
help="Path to git repository (defaults to current directory)"
"--path",
"-p",
help="Path to git repository (defaults to current directory)",
),
] = None,
label: Annotated[
Expand Down Expand Up @@ -246,8 +256,9 @@ def workspace_start(
path: Annotated[
Optional[str],
typer.Option(
"--path", "-p",
help="Path to workspace directory (defaults to current directory)"
"--path",
"-p",
help="Path to workspace directory (defaults to current directory)",
),
] = None,
repos: Annotated[
Expand All @@ -262,6 +273,13 @@ def workspace_start(
bool,
typer.Option("--open", help="Automatically open the workspace after creation"),
] = False,
pull_default: Annotated[
bool,
typer.Option(
"--pull-default",
help="Pull each repo's default branch (via origin/HEAD) before creating workspace branches",
),
] = False,
):
"""
Start a new multi-repository workspace.
Expand All @@ -273,7 +291,13 @@ def workspace_start(
if repos:
repo_list = [r.strip() for r in repos.split(",") if r.strip()]

workspace.start_workspace_session(label, workspace_path=path, repos=repo_list, open_session=open_session)
workspace.start_workspace_session(
label,
workspace_path=path,
repos=repo_list,
open_session=open_session,
pull_default=pull_default,
)


@workspace_app.command("ls")
Expand Down
Loading