# Asset Preview
Source: https://docs.diversion.dev/advanced/asset_preview
Preview your images, 3D models, and code directly in Diversion
Click any supported file in Diversion to preview it instantly—no need to open external applications.
## 3D Models
Preview and inspect 3D models with an interactive viewer. Rotate the camera around your model to examine it from any angle.
**Supported formats:**
* .gltf, .glb
* .fbx
* .obj
**File size limit:** 25 MB
## Images
**Supported formats:**
.jpg, .jpeg, .png, .gif, .webp, .tif, .tiff, .bmp, .ico, .svg
**File size limit:** 2 MB
## Unreal Engine Assets
Preview `.uasset` files by extracting their embedded thumbnails.
**File size limit:** 2 MB
## Code and Shaders
Preview text-based files with syntax highlighting.
**Supported formats:**
* .uproject, .uplugin
* .usf, .ush (Unreal Shader Format)
* .glsl, .hlsl
* .ispc, .isph
**File size limit:** 2 MB
# Obliterate
Source: https://docs.diversion.dev/advanced/obliterate
Permanently delete file blobs from a repository to reclaim storage and remove sensitive content.
`obliterate` permanently deletes the underlying blob storage for every version of files that match a path pattern, across all branches and commits. Unlike `dv rm`, which records a deletion in history but keeps the old versions reachable, obliterate removes the bytes themselves and rewrites references in history so the blobs cannot be retrieved.
Use it when:
* A very large file (game build, dataset, mistakenly committed binary) is consuming storage and is no longer needed in history.
* A secret, credential, or other sensitive file was committed and must be expunged.
Obliterate is **destructive and irreversible**. There is no undo. Always run a preview first and read the plan carefully before executing.
## Requirements
* You must be a [**repository admin**](/basic/access-levels#organization-level-access).
* Obliterate is not supported on git-synced repositories.
## How It Works
1. You supply one or more path globs (e.g. `'/assets/*.psd'`).
2. The server resolves every (path, version) match across the repo's history.
3. Each match is classified as either **deletable** (the underlying blob is only reachable through paths covered by your globs) or **not deleted** (the same blob content is reachable through some other path that you did not include).
4. On execute, the deletion runs asynchronously. You get back a `job_id` you can poll for progress.
The "not deleted" partition matters because Diversion stores file contents by hash -- the same bytes shared across paths are stored once. If the same content also lives at another path you did not include, the storage stays. The preview tells you exactly which other paths are blocking deletion -- you can widen your glob set and re-run.
## Glob Syntax
Patterns are **anchored to the repo root**. Always quote them so your shell does not expand the wildcards.
| Pattern | Matches |
| ------------------- | ----------------------------------------------------- |
| `/assets/*.psd` | `.psd` files directly under `/assets/`, root-anchored |
| `/assets/.../*.psd` | `.psd` files anywhere under `/assets/` (recursive) |
| `/.../secrets.env` | Any file named `secrets.env` anywhere in the repo |
| `/build/large.bin` | One specific file |
The preview returns a warning if a pattern is broadly unanchored (e.g. matches across the entire repo, or only at the root when you probably meant recursive). Redundant patterns -- ones already covered by another pattern in the same call -- are also flagged.
## Preview
Always start with a preview. Nothing changes on the server.
```bash theme={null}
dv obliterate preview '/assets/old_textures/*.psd'
```
The preview returns:
* **Headline counts**: deletable versions / files, not-deleted versions / files, and any matches in shared (grouped) storage that obliterate cannot reach.
* **Reclaim estimate**: total bytes that will be freed, deduplicated by content hash (the same blob at N paths counts once).
* **Deletable paths**: per-path summary -- versions and total bytes -- sorted by largest reclaim first.
* **Not deleted paths**: per-path summary plus `unblock_paths`: the other paths in the repo that still hold the same content. Add them to your glob set if you want the blob removed.
* **Per-glob summary**: for each input glob, the files / versions / total bytes it matched on its own (before cross-glob deduplication). Only surfaced in JSON output, and in the human CLI's per-glob block when you pass more than one glob.
* **Warnings**: surfaced when a glob is broadly unanchored or redundant.
Pass multiple globs in one call to plan their combined obliteration:
```bash theme={null}
dv obliterate preview '/assets/*.psd' '/builds/.../*.pak'
```
### Human vs JSON output
The human CLI shows the **top 20** deletable / not-deleted paths sorted by bytes desc, with a trailing line like `... and 980 more (use --json for the full list)` when the result was capped. The server returns the full byte-desc-sorted lists; only the display is capped.
For the full machine-readable plan, pass `--json`:
```bash theme={null}
dv obliterate preview --json '/assets/old_textures/*.psd' | jq '.deletable_paths | length'
```
`--json` emits a single JSON document on stdout with banners and warnings suppressed (warnings move into a `warning` string field on the document).
## Execute
Once the preview matches what you intend to delete:
```bash theme={null}
dv obliterate execute '/assets/old_textures/*.psd'
```
You will be prompted to type the repository name or ID to confirm. Pass `--yes` to skip the prompt (for scripting):
```bash theme={null}
dv obliterate execute --yes '/assets/old_textures/*.psd'
```
Execute returns the same plan as preview plus a `job_id` and starts polling the job until it reaches a terminal state. The polling cap is **18 seconds** (status endpoint every 3 seconds); for shorter jobs you will see the run complete inline, and for longer jobs the CLI prints the `job_id` and exits, leaving you to follow up with `dv obliterate status`.
Flags:
* `--nowait` -- enqueue and exit immediately without polling. The CLI prints the `job_id` and you check progress yourself.
* `--json` -- emit a single JSON document instead of the human banner. **Requires `--yes`** -- an interactive confirmation prompt would corrupt the JSON stream.
Exit codes:
| Code | Meaning |
| ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0` | Polling reached a terminal state and the job completed without failures. |
| `2` | Polling reached a terminal state and the job had one or more failed deletions. |
| `101` | The 18s polling cap elapsed with the job still in progress. Distinguishes "gave up waiting" from "done" so scripts can branch on it; follow up with `dv obliterate status`. |
`execute` returns as soon as the job is enqueued -- the actual deletion runs in the background, which is why you poll the status endpoint for progress.
Concurrent commits to the same files during an obliterate run are an edge case. Avoid running obliterate while other users are actively committing to the targeted paths.
## Tracking a Job
Each execute returns a `job_id` (e.g. `dv.obliterate.593d2b8a8dbf47559bcc73c8bcf54f41`). Check progress with:
```bash theme={null}
dv obliterate status
```
The response carries an overall `status` plus per-row counts:
```
Obliterate job dv.obliterate.593d2b8a8dbf47559bcc73c8bcf54f41
Status: in_progress
Counts: pending=18200 done=11800 failed=0
Started: 2026-06-18T08:39:01.147736+00:00
```
### Status values
| Status | Meaning |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `queued` | The worker has not started yet. |
| `in_progress` | Worker is running. `pending` is dropping as batches complete; `done` and `failed` are growing. |
| `succeeded` | Worker finished and all rows are `done`. |
| `failed` | Worker finished but one or more rows are `failed`. The response includes the first 20 errors with the failing SHA and a truncated error message. |
| `archived` | The job has aged out of the queue but its counts are still inspectable. |
A 404 from the status endpoint means there is no obliterate job with that id in this repo.
## What Gets Touched
* **History**: the obliterated file versions are removed from the repo's change log.
* **Open merges**: any open merge whose conflict referenced an obliterated file is closed, since finalizing it would otherwise produce a commit with a dead reference.
## Limits
* The preview/execute resolution call has a server-side time budget (60 seconds). If your glob matches too many files, the call is rejected with an error asking you to narrow the pattern. Split the work into more specific glob sets and run them sequentially.
* Files stored in **shared (grouped) storage** -- small files packed together for efficiency -- cannot be individually obliterated. The preview reports them as a separate skipped count so you know how many were excluded.
## Related
* [`dv obliterate`](/cmd-ref/obliterate) -- CLI reference
* [Storage](/concepts/storage) -- how blobs are stored and shared
* [Going back in time](/basic/going-back-in-time) -- non-destructive history navigation
# Pre-Commit Hooks
Source: https://docs.diversion.dev/advanced/pre-commit-hooks
Run custom scripts before commits to validate changes, enforce standards, and automate checks.
Pre-commit hooks let you run custom scripts that automatically validate your changes before each commit. If the script exits with a non-zero code, the commit is blocked - giving you a chance to fix issues before they reach the repository.
## Overview
Hooks are executable scripts stored in a `.dvhooks/` directory at the root of your repository. Because they live inside the repository, they sync to all collaborators just like any other file.
**Common use cases:**
* Lint and syntax checks
* Code formatting enforcement
* Preventing commits of large or forbidden files
* Custom project-specific validation
**How it works:**
* Before a commit, Diversion runs the `.dvhooks/pre-commit` script with the committed files as command-line arguments
* Exit code `0` means the hook passed - the commit proceeds
* Any non-zero exit code means the hook failed - the commit is blocked
* The hook's stdout/stderr output is displayed to the user
Pre-commit hooks are client-side only. They run when committing via the CLI or Desktop app. Commits made directly through the WebApp or API bypass hooks.
## Creating a Pre-Commit Hook
Create a `.dvhooks` directory at the root of your repository:
```bash theme={null}
mkdir .dvhooks
```
Create a `pre-commit` script inside `.dvhooks/`. The script can be written in any language, as long as it's executable.
```bash Mac/Linux (.dvhooks/pre-commit) theme={null}
#!/bin/sh
echo "Running pre-commit checks..."
# Committed files are passed as arguments ($@)
for file in "$@"; do
if echo "$file" | grep -q '\.js$'; then
if grep -q "console.log" "$file"; then
echo "Error: Remove console.log from $file before committing."
exit 1
fi
fi
done
echo "All checks passed."
exit 0
```
```bat Windows (.dvhooks/pre-commit.bat) theme={null}
@echo off
echo Running pre-commit checks...
REM Committed files are passed as arguments (%*)
for %%f in (%*) do (
echo Checking %%f
)
echo All checks passed.
exit /b 0
```
```powershell Windows (.dvhooks/pre-commit.ps1) theme={null}
Write-Host "Running pre-commit checks..."
# Committed files are passed as arguments ($args)
foreach ($file in $args) {
if ($file -match '\.js$') {
if (Select-String -Path $file -Pattern "console.log" -Quiet) {
Write-Host "Error: Remove console.log from $file before committing."
exit 1
}
}
}
Write-Host "All checks passed."
exit 0
```
On Mac/Linux, make the script executable:
```bash theme={null}
chmod +x .dvhooks/pre-commit
```
Commit the `.dvhooks/` directory to share the hook with your collaborators:
```bash theme={null}
dv commit .dvhooks -m "Add pre-commit hook"
```
Once committed, every collaborator on the branch will have the hook and it will run automatically before their commits.
## File Arguments
The files being committed are passed to your hook script as **command-line arguments**. Your script can access them via `$@` (Mac/Linux) or `%*` (Windows).
When the file list is too large for a single command invocation, Diversion automatically splits it into chunks and runs the hook multiple times in parallel. If any invocation fails, the commit is blocked.
**Example - check committed files for large binaries:**
```bash Mac/Linux theme={null}
#!/bin/sh
# Reject files larger than 100MB
MAX_SIZE=$((100 * 1024 * 1024))
for file in "$@"; do
if [ -f "$file" ]; then
size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
if [ "$size" -gt "$MAX_SIZE" ]; then
echo "Error: $file is too large ($(($size / 1024 / 1024))MB, limit 100MB)."
exit 1
fi
fi
done
exit 0
```
```bat Windows theme={null}
@echo off
REM Check committed files
for %%f in (%*) do (
echo Checking: %%f
)
exit /b 0
```
## Environment Variables
Diversion also passes context to your hook script via environment variables:
| Variable | Description |
| ------------------- | ----------------------------------- |
| `DV_REPO_ROOT` | Absolute path to the workspace root |
| `DV_COMMIT_MESSAGE` | The commit message |
| `DV_BRANCH` | Current branch name |
**Example - require a ticket number in the commit message:**
```bash Mac/Linux theme={null}
#!/bin/sh
# Require commit messages to contain a ticket reference (e.g., PROJ-123)
if ! echo "$DV_COMMIT_MESSAGE" | grep -qE '[A-Z]+-[0-9]+'; then
echo "Error: Commit message must include a ticket number (e.g., PROJ-123)."
echo "Your message: $DV_COMMIT_MESSAGE"
exit 1
fi
exit 0
```
```bat Windows theme={null}
@echo off
REM Require commit messages to contain a ticket reference (e.g., PROJ-123)
echo %DV_COMMIT_MESSAGE% | findstr /R "[A-Z]*-[0-9]*" >nul 2>&1
if %errorlevel% neq 0 (
echo Error: Commit message must include a ticket number (e.g., PROJ-123).
echo Your message: %DV_COMMIT_MESSAGE%
exit /b 1
)
exit /b 0
```
## Skipping Hooks
Use the `--no-verify` flag to bypass pre-commit hooks for a single commit:
```bash theme={null}
dv commit -a -m "quick fix" --no-verify
```
This is useful for urgent fixes when you need to commit without running validation.
## Behavior Details
* **Timeout**: Hooks have a 60-second timeout. If the hook doesn't finish in time, the commit is blocked with a timeout message.
* **Working directory**: The hook runs with the workspace root as its working directory.
* **Output limit**: Hook output is capped at 1 MB. Output beyond that limit is truncated.
* **Output display**: Hook output is always shown to the user, whether the hook passes or fails.
* **Platform detection**:
* **Mac/Linux**: Diversion looks for an executable file named `pre-commit` in `.dvhooks/`. If the file exists but isn't executable, you'll see an error prompting you to run `chmod +x`.
* **Windows**: Diversion looks for `pre-commit.bat`, `pre-commit.cmd`, or `pre-commit.ps1` in `.dvhooks/` (checked in that order).
# Selective Sync
Source: https://docs.diversion.dev/advanced/selective-sync
Only sync the files you need
This one is for artists who don't want code, or for developers who aren't artistically inclined.
## What is Selective Sync?
Selective Sync is a feature that allows you to choose which folders you want to sync locally. This will allow you to only have the files you need to work on, saving space on your computer.
## How to use Selective Sync
Open the workspace's **... (more options) menu** next to the workspace selector ("THIS WORKSPACE") and choose Selective sync.
From your local folder, run `dv view`, or click the View Repo button in the UI.
Click the **... (more options) button** next to the workspace selector to open the "THIS WORKSPACE" menu, then choose **Selective sync** ("Choose which folders sync to this machine").
### Unsyncing a folder
Let's take a look at `folder 1`.
In the UI:
And locally:
Let's unsync `folder 1.2`. Unselect the folder in the UI and hit Save.
Locally, the folder disappears automatically.
It's also missing in the UI.
### What about my uncommitted changes?
Have no fear! If you have any uncommitted changes, you won't be able to change your selective sync settings. Let's see what that looks like.
Inside `folder 1.1`, let's make changes to `text document 1.1.1.txt` and save.
Back in the workspace settings, let's try to unsync `folder 1.1`.
We got an error message! We'll have to commit or discard our changes before unsyncing the folder.
## Loose files
Right now, we can only selectively sync folders. This means that files are handled differently, if they're not in a folder.
Let's take a look at `folder 2`.
Notice that it has a file directly under it - `text document 2.1.txt`. In this situation, unsyncing `folder 2.1` will also unsync `text document 2.1.txt`! That's despite the file being a sibling of the folder and not a child of it. This is because `folder 2` will be marked as partially synced, so only explicitly synced folders (in this case, `folder 2.2`) will be kept.
This still supports the main use-case of this feature:
1. Artists who don't want to sync code locally can ignore the root `Source` folder, or equivalent.
2. Developers who don't want to sync heavy assets can ignore the root `Content` folder, or equivalent.
## Per workspace
The selective sync feature works on a per-workspace basis. This means that you can have different selective sync settings for different workspaces. This is useful if you have multiple projects in the same repo, or if you're working on different parts of the same project.
# Agent Quickstart
Source: https://docs.diversion.dev/agent-quickstart
Set up Diversion as the version control for your coding agent
This page is written for **AI coding agents** (Claude Code, Cursor, Codex, or any tool that runs shell commands). It explains how to use Diversion as the version control for a repository with the `dv` CLI. Diversion is a cloud-native version control system — an alternative to Git and Perforce, built for large binary files with automatic sync.
**Use Diversion when** your repo has large or binary files (game assets, models, datasets, build artifacts) that Git and Git LFS handle poorly, when you want commits to sync to teammates automatically (no push or pull), or when you're running multiple agents that each need an isolated copy of the repo.
Setting up Diversion yourself with the desktop app? Start with the [Quickstart](/quickstart) instead.
**Pointing an agent here?** The full machine-readable docs index lives at [`docs.diversion.dev/llms.txt`](https://docs.diversion.dev/llms.txt) (and [`/llms-full.txt`](https://docs.diversion.dev/llms-full.txt) for the complete text). Give your agent that URL together with this page.
## How Diversion differs from Git
Diversion is not Git. Internalize these rules before running commands:
* **Auto-sync — no `push` or `pull`.** Every commit replicates to the cloud and to teammates automatically. There is no `dv push` or `dv pull`.
* **No staging area — no `git add`.** Diversion tracks every change in the working tree continuously. You commit files directly.
* **One workspace = one working directory.** A *workspace* is a local copy of a single branch. To work on two branches at once, use two workspaces — see [Run agents in parallel](#run-agents-in-parallel).
* **Always pass a subcommand.** Run `dv status`, `dv commit`, and so on. Running bare `dv` opens an interactive shell; avoid it in non-interactive or agent contexts.
## Install
```bash theme={null}
curl -sL https://get.diversion.dev/unix | bash ; export PATH="$HOME/.diversion/bin:$PATH"
```
Add the `export PATH` line to your shell profile (`~/.bashrc` or `~/.zshrc`) to make it permanent.
Download and run the [Windows installer](https://get.diversion.dev/win).
Confirm the install:
```bash theme={null}
dv version
```
## Authenticate
```bash theme={null}
dv login
```
This opens a browser to sign in. **A human runs this once** in the environment where the agent operates; the agent reuses the session afterward.
**Headless or CI agents (no browser):** generate an API token (in the web app: avatar → **Integrations** → **Generate a new API token**) and authenticate non-interactively with `dv authenticate ` — no browser needed. The [CI/CD guide](/ci-cd) has the full setup. The same token also works as a `Bearer` token against the [REST API](/api-reference/introduction). API access requires the [Pro plan or above](https://www.diversion.dev/pricing).
## Core commands
```bash theme={null}
# Start tracking a new project in the current directory
dv init
# Get a working copy of an existing repository
dv clone [path]
# See what changed in the working tree
dv status
# Commit all current changes (replicates automatically — no push needed)
dv commit -a -m "your message"
# Create a new branch and switch to it
dv branch -c
# Switch to an existing branch, commit, or tag
dv checkout
# Merge another branch into the current one
dv merge
# View history
dv log
```
Full reference: [CLI Reference](/cmd-ref/about-cmd).
## Git → Diversion command map
| Git | Diversion (`dv`) |
| ---------------------------------- | ------------------------------------------------------- |
| `git clone ` | `dv clone [path]` |
| `git init` | `dv init` |
| `git add ` | *(not needed — changes are tracked automatically)* |
| `git status` | `dv status` |
| `git commit -am "msg"` | `dv commit -a -m "msg"` |
| `git push` / `git pull` | *(not needed — auto-sync)* |
| `git checkout -b ` | `dv branch -c ` |
| `git switch ` | `dv checkout ` |
| `git merge ` | `dv merge ` |
| `git log` | `dv log` |
| `git worktree add ` | `dv clone --new-workspace --ref ` |
## Run agents in parallel
To run agents in isolated workspaces — the Diversion equivalent of `git worktree` — clone the repository into a separate directory with its own workspace, **each on its own branch**. The workspaces are isolated on disk, and a dedicated branch per agent keeps their commits from interfering. (Agents that share a branch still auto-sync to it and can conflict — give each one its own branch.)
```bash theme={null}
# Create an isolated workspace on a dedicated branch
dv clone /tmp/-agent-1 --new-workspace --ref
```
The agent works inside `/tmp/-agent-1` and commits as usual — changes auto-sync to that branch. When the work is done, tear the workspace down:
```bash theme={null}
dv workspace # list workspaces to find the one to remove (id starts with dv.ws.)
dv unregister -f # run from inside /tmp/-agent-1 — detaches the local copy
dv workspace delete -f
rm -rf /tmp/-agent-1
```
Today this clones the full repository, including binary assets. For asset-heavy repositories (e.g. Unreal projects) that is a large download per workspace. Code-only ("selective sync") cloning from the CLI is on the roadmap.
## Next steps
The Diversion plugin for Claude Code links every commit to the conversation that produced it, so you can ask later *why* any change was made. Optional.
Every `dv` command, flag, and argument.
Automate Diversion over REST.
Diversion's built-in AI coding agent.
# Get billing information
Source: https://docs.diversion.dev/api-reference/account/get-billing-information
get /account/billing
Get billing information for the authenticated user
# Get client configuration
Source: https://docs.diversion.dev/api-reference/authentication/get-client-configuration
get /auth/config
Get configuration for the authenticated client including optional cache and update URLs
# Get enterprise login URL
Source: https://docs.diversion.dev/api-reference/authentication/get-enterprise-login-url
get /auth/enterprise
Get the enterprise login URL for a given organization
# Test token
Source: https://docs.diversion.dev/api-reference/authentication/test-token
get /auth/test
Test token validity and repo write access
# Accept a repository invitation
Source: https://docs.diversion.dev/api-reference/collaborators/accept-a-repository-invitation
post /repos/{repo_id}/invites/{invite_id}/accept
Accepts a repository collaboration invitation, granting the user access with the specified mode (READ, WRITE, ADMIN).
**Behavior:**
- If the repository belongs to an organization, the user is automatically added as an organization member if not already
- Restores any previously deleted workspaces for this user
**Returns:**
- `409 Conflict` if already a collaborator
- `204 No Content` on success
# Invite collaborator
Source: https://docs.diversion.dev/api-reference/collaborators/invite-collaborator
put /repos/{repo_id}/invites
Invite a collaborator to a repository
# List collaborators
Source: https://docs.diversion.dev/api-reference/collaborators/list-collaborators
get /repos/{repo_id}/collaborators
Get all collaborators and pending invites for repo
# Reject a repository invitation
Source: https://docs.diversion.dev/api-reference/collaborators/reject-a-repository-invitation
post /repos/{repo_id}/invites/{invite_id}/reject
Rejects a repository collaboration invitation without granting access.
**Behavior:**
The invitation is marked as redeemed with REJECTED status.
**Validation:**
- Invitation is addressed to the user's email
- Invitation hasn't been redeemed
- Invitation hasn't expired
**Returns:**
- `409 Conflict` if already processed
- `204 No Content` on success
# Revoke collaborator access
Source: https://docs.diversion.dev/api-reference/collaborators/revoke-collaborator-access
delete /repos/{repo_id}/collaborators/{user_id}
Revoke a user's access level to the repo
# Update collaborator access
Source: https://docs.diversion.dev/api-reference/collaborators/update-collaborator-access
patch /repos/{repo_id}/collaborators/{user_id}
Change a user's access level to the repo
# Developer Guide
Source: https://docs.diversion.dev/api-reference/developer-guide
Getting started with Diversion API
## Overview
This section describes how to use the Diversion API to build custom integrations and clients.
## Authentication
All API endpoints, unless stated otherwise, are authenticated using Bearer tokens.
```
Authorization: Bearer
```
## Base URL
All API endpoints are relative to the base URL `https://api.diversion.dev/v0`.
## Making Your First Request
Once you have your token, you can test that it works by making a request to the `/auth/test` endpoint:
```python Python theme={null}
import requests
response = requests.get(
"https://api.diversion.dev/v0/auth/test",
headers={"Authorization": "Bearer "}
)
print(response.status_code) # Should print 204
```
```typescript TypeScript theme={null}
const response = await fetch("https://api.diversion.dev/v0/auth/test", {
headers: {
"Authorization": "Bearer "
}
});
console.log(response.status); // Should print 204
```
```bash cURL theme={null}
curl -X GET "https://api.diversion.dev/v0/auth/test" \
-H "Authorization: Bearer "
```
```go Go theme={null}
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.diversion.dev/v0/auth/test", nil)
req.Header.Set("Authorization", "Bearer ")
client := &http.Client{}
resp, _ := client.Do(req)
fmt.Println(resp.StatusCode) // Should print 204
}
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Threading.Tasks;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var response = await client.GetAsync("https://api.diversion.dev/v0/auth/test");
Console.WriteLine((int)response.StatusCode); // Should print 204
```
## Real-World Example: Create a New Repo
See the endpoint's full documentation [here](/api-reference/repository-management/create-a-repo).
```python theme={null}
import requests
response = requests.post(
"https://api.diversion.dev/v0/repos",
headers={"Authorization": "Bearer "},
json={
"name": "my-repo",
"description": "My first repo"
}
)
print(response.json()) # Should print the created repo
```
## Error handling
Some common errors can be returned from most API endpoints and are listed below. Errors that are specific to an API endpoint are listed in the endpoint's documentation.
### Error format
All errors are returned in the following format:
```json theme={null}
{
"detail": "",
"status": ,
"title": ""
}
```
```jsonschema theme={null}
{
"type": "object",
"properties": {
"detail": {
"type": "string",
"description": "A detailed description of the error"
},
"status": {
"type": "integer",
"description": "HTTP status code",
"examples": [400, 401, 403, 404, 500]
},
"title": {
"type": "string",
"description": "A short, human-readable summary of the error type"
},
},
"required": ["detail", "status", "title"]
}
```
### Common errors
#### 400 Bad Request
Returned when the request is invalid.
Example response:
```json theme={null}
{
"detail": "'st' is too short\n\nFailed validating 'minLength' in schema:\n {'type': 'string',\n 'example': 'example_id',\n 'minLength': 3,\n 'maxLength': 128}\n\nOn instance:\n 'd'",
"status": 400,
"title": "Bad Request"
}
```
#### 401 Unauthorized
Returned when the authentication token is invalid or expired.
Example response:
```json theme={null}
{
"detail": "Invalid authentication token",
"status": 401,
"title": "Unauthorized"
}
```
#### 403 Forbidden
Returned when the authentication token is valid but the user is not authorized to access the endpoint.
Example response:
```json theme={null}
{
"detail": "User not authorized to perform the requested action on the resource",
"status": 403,
"title": "Forbidden"
}
```
#### 404 Not Found
Returned when the requested resource is not found.
Example response:
```json theme={null}
{
"detail": "Workspace id not found",
"status": 404,
"title": "Not Found"
}
```
#### 500 Internal Server Error
Returned when the server encountered an unexpected condition that prevented it from fulfilling the request.
Example response:
```json theme={null}
{
"detail": "Internal server error",
"status": 500,
"title": "Internal Server Error"
}
```
# Delete file
Source: https://docs.diversion.dev/api-reference/file-mutation/delete-file
delete /repos/{repo_id}/files/{ref_id}/{path}
Deletes a file or directory at the specified path in a workspace.
**Requirements:**
- The `ref_id` must be a workspace ID
- Requires a client ID header
**Behavior:**
The deletion is recorded in the workspace's draft commit and can be reverted before committing.
**Returns:**
- `404 Not Found` if the path doesn't exist
- `202 Accepted` on successful deletion
# Move file
Source: https://docs.diversion.dev/api-reference/file-mutation/move-file
patch /repos/{repo_id}/files/{ref_id}/{path}
Moves or renames a file from the current path to a new path specified in the `new_path` parameter.
**Requirements:**
- The `ref_id` must be a workspace ID
- Requires a client ID header
**Validation:**
Both paths are normalized and validated before the operation.
**Returns:**
- `404 Not Found` if the source path doesn't exist
- `202 Accepted` on successful move
# Upload file
Source: https://docs.diversion.dev/api-reference/file-mutation/upload-file
post /repos/{repo_id}/files/{ref_id}/{path}
Creates or updates a file in a workspace.
**Requirements:**
- The `ref_id` must be a workspace ID
- Requires a client ID header
**File content options:**
- Inline as binary data
- Via storage hints (storage_backend, storage_uri, sha1, size)
**Parameters:**
- `mode` - specifies file permissions
- `mtime` - sets the modification time
**Validation:**
Reserved paths containing '.diversion' are rejected.
**Returns:**
- `202 Accepted` on success
- `204 No Content` if no change was made
# Introduction
Source: https://docs.diversion.dev/api-reference/introduction
Complete customization and integration with Diversion via APIs
If you're not looking to build a new client or a custom integration, you probably
want to look at the [Quickstart](/quickstart) guide.
## Welcome
This section describes client-facing APIs. Diversion's native clients and web app use these endpoints. Server-side APIs
are coming soon, if you want early preview access [contact us](mailto:hello@diversion.dev).
## Next Steps
* Read the [Developer Guide](/api-reference/developer-guide)
# Accept organization invite
Source: https://docs.diversion.dev/api-reference/organization-management/accept-organization-invite
post /organizations/{org_id}/invites/{invite_id}/accept
Accepts an organization invitation, adding the user as a member with the role specified in the invite.
**Validation checks:**
- Invitation is addressed to the user's email
- Invitation is still pending
- Invitation hasn't expired
**Returns:**
- `409 Conflict` if the user is already a member
- `403 Forbidden` if the invite isn't for this user
- `204 No Content` on success
# Change member role
Source: https://docs.diversion.dev/api-reference/organization-management/change-member-role
patch /organizations/{org_id}/members/{user_id}/role
Update the role of an existing organization member
# Create organization
Source: https://docs.diversion.dev/api-reference/organization-management/create-organization
post /organizations
Creates a new organization with the user as the owner If the user is already a member of an organization with the same name, the request will fail
# Get organization details
Source: https://docs.diversion.dev/api-reference/organization-management/get-organization-details
get /organizations/{org_id}
Retrieves detailed information about a specific organization including:
- Name
- Description
- Owner ID
- Total storage usage
- Warning group status
**Requirements:**
Requires READ access to the organization (user must be a member).
**Returns:**
- `404 Not Found` if the organization doesn't exist or user lacks access
# Get organization member
Source: https://docs.diversion.dev/api-reference/organization-management/get-organization-member
get /organizations/{org_id}/members/{user_id}
Get details about a specific member in the organization
# Invite member to organization
Source: https://docs.diversion.dev/api-reference/organization-management/invite-member-to-organization
post /organizations/{org_id}/invites
Sends an invitation to the specified user to join the organization with the chosen role.
# Leave organization
Source: https://docs.diversion.dev/api-reference/organization-management/leave-organization
post /organizations/{org_id}/leave
Leave the organization as a member. Organization owners and repository owners cannot leave until they transfer ownership.
# List accessible repos
Source: https://docs.diversion.dev/api-reference/organization-management/list-accessible-repos
get /organizations/{org_id}/members/{user_id}/repos
Returns a list of repositories the member will lose access to if removed.
# List organization invites
Source: https://docs.diversion.dev/api-reference/organization-management/list-organization-invites
get /organizations/{org_id}/invites
Retrieves a list of users who have been invited to the organization but have not yet accepted the invitation.
# List organization members
Source: https://docs.diversion.dev/api-reference/organization-management/list-organization-members
get /organizations/{org_id}/members
Get a paginated list of all members in the organization, sorted by name
# List organization repositories
Source: https://docs.diversion.dev/api-reference/organization-management/list-organization-repositories
get /organizations/{org_id}/repos
Get a list of all repositories in the organization
# List pending org invites
Source: https://docs.diversion.dev/api-reference/organization-management/list-pending-org-invites
get /organizations/invites
Retrieves all pending organization invitations for the current user based on their email address. Only returns non-expired invitations with optional status filtering (defaults to PENDING). Each invite includes organization details, inviting user information, role assignment, and expiration time. Invitations are automatically sent to the user's registered email address.
# List user's organizations
Source: https://docs.diversion.dev/api-reference/organization-management/list-users-organizations
get /organizations
Lists all organizations the user is a member of, optionally filtered to show only owned organizations when `owned=true`.
**Sorting:**
Results are sorted alphabetically by organization name.
**Information included:**
Each organization includes:
- Basic metadata
- A flag indicating if it's in a warning group (quota breach or payment issue)
**Returns:**
An empty list if the user is not a member of any organizations.
# Organization subscriptions
Source: https://docs.diversion.dev/api-reference/organization-management/organization-subscriptions
get /organizations/subscription-info
Get subscription and plan details for organizations the user is a member of
# Reject organization invite
Source: https://docs.diversion.dev/api-reference/organization-management/reject-organization-invite
post /organizations/{org_id}/invites/{invite_id}/reject
Rejects an organization invitation without adding the user as a member.
**Behavior:**
The invitation status is updated to REJECTED and the user will not be added to the organization.
**Validation checks:**
- Invitation is addressed to the user's email
- Invitation is still pending
- Invitation hasn't expired
**Returns:**
- `409 Conflict` if already processed
- `204 No Content` on success
# Remove organization member
Source: https://docs.diversion.dev/api-reference/organization-management/remove-organization-member
delete /organizations/{org_id}/members/{user_id}
Only organization admins can delete members.
# Rename organization
Source: https://docs.diversion.dev/api-reference/organization-management/rename-organization
patch /organizations/{org_id}
Change the name of an organization. Only admins can perform this action.
# Revoke invites by email
Source: https://docs.diversion.dev/api-reference/organization-management/revoke-invites-by-email
post /organizations/{org_id}/invites/revoke
Revokes all organization and repository invitations for a specific email address within the organization.
# Get Perforce import state
Source: https://docs.diversion.dev/api-reference/perforce-repository-import/get-perforce-import-state
get /repos/{repo_id}/p4-import-state
Retrieve the current state of the continuous Perforce import job for this repository, including the last imported changelist, error information, and running status.
# Mark P4 import as running
Source: https://docs.diversion.dev/api-reference/perforce-repository-import/mark-p4-import-as-running
post /repos/{repo_id}/p4-import-state/mark-running
Mark the Perforce import job as currently running by generating a new running_job_id and setting the start timestamp. This should be called when a continuous import job begins.
# Mark P4 import as stopped
Source: https://docs.diversion.dev/api-reference/perforce-repository-import/mark-p4-import-as-stopped
post /repos/{repo_id}/p4-import-state/mark-stopped
Mark the Perforce import job as no longer running by clearing the running_job_id and started_unix timestamp. This should be called when a continuous import job completes or stops. The job will only be marked as stopped if the current running_job_id matches the one in the database to prevent race conditions.
# Update P4 import state
Source: https://docs.diversion.dev/api-reference/perforce-repository-import/update-p4-import-state
post /repos/{repo_id}/p4-import-state
Initialize or update the state of a continuous Perforce import job after manual initial import. Creates or updates a P4ImportJob record tracking the last imported changelist for incremental syncing.
# Create branch
Source: https://docs.diversion.dev/api-reference/repository-branch-manipulation/create-branch
post /repos/{repo_id}/branches
Create a branch, optionally with a branch description
# Delete branch
Source: https://docs.diversion.dev/api-reference/repository-branch-manipulation/delete-branch
delete /repos/{repo_id}/branches/{branch_id}
Delete a branch. The default branch cannot be deleted.
# Get branch details
Source: https://docs.diversion.dev/api-reference/repository-branch-manipulation/get-branch-details
get /repos/{repo_id}/branches/{branch_id}
Retrieves detailed information about a specific branch including:
- ID
- Name
- Author
- Creation time
- Associated commit ID
- Description
- Deletion status
- Draft commit status
**Requirements:**
Requires READ access to the repository.
**Returns:**
Branch details with enriched author information from the user database.
# List branches
Source: https://docs.diversion.dev/api-reference/repository-branch-manipulation/list-branches
get /repos/{repo_id}/branches
Get a list of all branches in the repo
# Update a branch
Source: https://docs.diversion.dev/api-reference/repository-branch-manipulation/update-a-branch
patch /repos/{repo_id}/branches/{branch_id}
Updates branch properties including:
- Name
- Description
- The commit it points to
- Protection status and configuration
**Parameters:**
The following optional fields can be provided in the request body:
- `branch_name`
- `branch_description`
- `commit_id`
- `is_protected` - Whether the branch is protected (requires ADMIN access)
- `protection_config` - Configuration for protected branches (requires ADMIN access)
**Limitations:**
- Renaming branches is not supported for repositories synced with Git.
- Setting protection requires ADMIN access to the repository.
**Returns:**
- `409 Conflict` if a branch with the new name already exists
- `403 Forbidden` if attempting to modify protection without ADMIN access
- `204 No Content` on success
# Commit on behalf of author
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/commit-on-behalf-of-author
post /repos/{repo_id}/workspaces/{workspace_id}/commit-on-behalf
Commit workspace changes with custom author information and timestamp.
This endpoint is used for importing commits from external VCS systems (e.g., Perforce)
where the original author and timestamp should be preserved.
Requires Admin access to the repository.
# Commit workspace
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/commit-workspace
post /repos/{repo_id}/workspaces/{workspace_id}/commit
Commit workspace to base branch
# Count commit changes
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/count-commit-changes
get /repos/{repo_id}/commits/{commit_id}/count_changes
Get the number of changes in a commit
# Get commit details
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/get-commit-details
get /repos/{repo_id}/commits/{commit_id}
Get details of a specific commit
# Get commits bulk
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/get-commits-bulk
get /repos/{repo_id}/commits/bulk
Get bulk details of commits by their reference IDs
# List commits
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/list-commits
get /repos/{repo_id}/commits
Get a list of commits. (Executed on secondary shard)
# Revert commit
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/revert-commit
post /repos/{repo_id}/revert
The operation reverts any changes done in the single commit represented by revert_ref_id (compared to its own parent). These opposing changes are then applied into the branch represented by base_id. If any changes were done between revert_ref_id and base_id, they will be checked for conflicts with the revert changes.
# Revert to commit
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/revert-to-commit
post /repos/{repo_id}/revert_to_commit_workspace
The operation gets the file version in the specific commit and applies it to the workspace. Changes are the saved to the workspace.
# Update commit message
Source: https://docs.diversion.dev/api-reference/repository-commit-manipulation/update-commit-message
patch /repos/{repo_id}/commits/{commit_id}
Update a commit message. Can only be called on commits authored by the current user.
# Compare refs
Source: https://docs.diversion.dev/api-reference/repository-content-comparison/compare-refs
get /repos/{repo_id}/compare
Compare two refs (commit/branch/workspace/tag/tree) in this repo
# Close draft commit
Source: https://docs.diversion.dev/api-reference/repository-draft-commits/close-draft-commit
post /repos/{repo_id}/draft-commits/{draft_commit_id}/close
Close a draft commit. This operation changes the status to 'closed' and marks the draft branch as deleted.
# List draft commits
Source: https://docs.diversion.dev/api-reference/repository-draft-commits/list-draft-commits
get /repos/{repo_id}/draft-commits
List draft commits for the current user
# Create a path permission
Source: https://docs.diversion.dev/api-reference/repository-granular-permissions/create-a-path-permission
post /repos/{repo_id}/granular-permissions
Create a new path permission rule for this repository
# Delete a path permission
Source: https://docs.diversion.dev/api-reference/repository-granular-permissions/delete-a-path-permission
delete /repos/{repo_id}/granular-permissions/{permission_id}
Delete a path permission rule from the repository
# Get path permission details
Source: https://docs.diversion.dev/api-reference/repository-granular-permissions/get-path-permission-details
get /repos/{repo_id}/granular-permissions/{permission_id}
Get details of a specific path permission rule
# List granular permissions
Source: https://docs.diversion.dev/api-reference/repository-granular-permissions/list-granular-permissions
get /repos/{repo_id}/granular-permissions
List all granular permissions configured for this repository
# Update a path permission
Source: https://docs.diversion.dev/api-reference/repository-granular-permissions/update-a-path-permission
patch /repos/{repo_id}/granular-permissions/{permission_id}
Update an existing path permission rule
# Create a repo
Source: https://docs.diversion.dev/api-reference/repository-management/create-a-repo
post /repos
Create an empty repo. Optionally also skip the default `.dvignore` file or make it branchless.
# List pending repo invites
Source: https://docs.diversion.dev/api-reference/repository-management/list-pending-repo-invites
get /repos/invites
Retrieves all pending repository collaboration invitations for the current user based on their email address.
**Filtering:**
Returns non-expired invitations with optional status filtering (defaults to PENDING).
**Each invite includes:**
- Repository name
- Organization (if applicable)
- Inviting user details
- Access mode
- Expiration time
**Use case:**
Used by clients to display pending invitations requiring user action.
# List user's repositories
Source: https://docs.diversion.dev/api-reference/repository-management/list-users-repositories
get /repos
Get a list of repositories accessibly by the authenticated user
# Delete repository
Source: https://docs.diversion.dev/api-reference/repository-manipulation/delete-repository
delete /repos/{repo_id}
Delete a repo. All files, workspaces, commits, branches permissions etc. associated with the repo will be deleted.
# Download file tree snapshot
Source: https://docs.diversion.dev/api-reference/repository-manipulation/download-file-tree-snapshot
get /repos/{repo_id}/tree_snapshot/{ref_id}
Get URL to file tree snapshot. Either one of workspace, branch or commit ID needs to be specified as ref ID. If the requested commit doesn't have a snapshot, the endpoint will return the nearest available ancestor snapshot along with the `commit_id` of that snapshot.
# Get blob contents
Source: https://docs.diversion.dev/api-reference/repository-manipulation/get-blob-contents
get /repos/{repo_id}/blobs/{ref_id}/{path}
Get blob contents snapshot. Either one of workspace, branch or commit ID needs to be specified
# Get file entry
Source: https://docs.diversion.dev/api-reference/repository-manipulation/get-file-entry
get /repos/{repo_id}/files/{ref_id}/{path}
Get file entry (either tree or blob). Either one of workspace, branch or commit ID needs to be specified
# Get file history
Source: https://docs.diversion.dev/api-reference/repository-manipulation/get-file-history
get /repos/{repo_id}/files/history/{ref_id}/{path}
Retrieves the complete change history for a specific file or directory path from a given reference (branch or commit).
**Returns:**
A list of commits that modified the path, with each entry containing:
- Commit details
- File entry state at that commit
**Features:**
- Supports pagination via optional `limit` and `skip` parameters
**Requirements:**
Requires READ access to the repository.
# Get file tree
Source: https://docs.diversion.dev/api-reference/repository-manipulation/get-file-tree
get /repos/{repo_id}/trees/{ref_id}
Get file tree snapshot. Either one of workspace, branch or commit ID needs to be specified as ref ID
# Get repository details
Source: https://docs.diversion.dev/api-reference/repository-manipulation/get-repository-details
get /repos/{repo_id}
Retrieves detailed repository information including:
- Name
- Description
- Size in bytes
- Owner ID
- Creation timestamp
- Digest method
- Default branch details
- Git sync configuration (if enabled)
- Organization ID (if part of an organization)
- Default auto-forwarding status
**Requirements:**
Requires READ access to the repository.
**Returns:**
- `404 Not Found` if the repository doesn't exist or user lacks access
# Get tree content stream
Source: https://docs.diversion.dev/api-reference/repository-manipulation/get-tree-content-stream
get /repos/{repo_id}/tree_content/{ref_id}
Get file tree snapshot. Either one of workspace, branch or commit ID needs to be specified as ref ID
# Import Git repository
Source: https://docs.diversion.dev/api-reference/repository-manipulation/import-git-repository
post /repos/{repo_id}/import
Import a Git repo with all history from a Git URL. {repo_id} must have no commits and no branches, or be already marked as synced with the same git_url. The git repo URL must have http credentials embedded or otherwise hosted on Github and the owner has the Diversion Github app integration set up.
# Rename repository
Source: https://docs.diversion.dev/api-reference/repository-manipulation/rename-repository
post /repos/{repo_id}/rename
Change the name of a repository
# Set default branch
Source: https://docs.diversion.dev/api-reference/repository-manipulation/set-default-branch
post /repos/{repo_id}/default_branch
Change default branch for a repository
# Set repo auto-forwarding
Source: https://docs.diversion.dev/api-reference/repository-manipulation/set-repo-auto-forwarding
post /repos/{repo_id}/set_def_auto_forwarding
Set default auto-forwarding value, which determines whether they automatically advance to the latest commit when their branch receives new commits. This only affects workspaces created after this setting is changed. Existing workspaces retain their current auto-forwarding status.
# Sync Git repository
Source: https://docs.diversion.dev/api-reference/repository-manipulation/sync-git-repository
post /repos/{repo_id}/sync
Sync all history from Git. The repo must already be associated with a Git repo (see import).
# Transfer ownership
Source: https://docs.diversion.dev/api-reference/repository-manipulation/transfer-ownership
post /repos/{repo_id}/transfer
Transfer repository ownership or attach to an organization.
Two modes of operation:
- Transfer ownership within an organization: Provide new_owner_user_id to change the repository owner to another user in the same organization
- Transfer personal repo to organization: Provide target_organization_id to attach a personal repository to an organization
Exactly one of new_owner_user_id or target_organization_id must be provided.
# Verify Git repository import
Source: https://docs.diversion.dev/api-reference/repository-manipulation/verify-git-repository-import
post /repos/import/check
The git repo URL must have http credentials embedded or otherwise hosted on Github and the owner has the Diversion Github app integration set up.
# Get merge details
Source: https://docs.diversion.dev/api-reference/repository-merge-manipulation/get-merge-details
get /repos/{repo_id}/merges/{merge_id}
Retrieves detailed information about a specific open merge including all conflicts with their base, other, and result indices.
**Each conflict shows:**
- File paths
- Modes
- Sizes
- Storage locations
- Resolution status
**Returns:**
- `404 Not Found` if the merge doesn't exist
- `405 Method Not Allowed` if the merge is obsolete
# List open merges
Source: https://docs.diversion.dev/api-reference/repository-merge-manipulation/list-open-merges
get /repos/{repo_id}/merges
Lists all open merge operations for a repository, optionally filtered by `base_id` (target branch) and `other_id` (source branch/commit).
**Sorting:**
Results are sorted with the current user's merges first, then by creation time.
**Information included:**
Each merge includes basic information without conflict details.
**Requirements:**
Requires READ access to the repository.
# Merge refs
Source: https://docs.diversion.dev/api-reference/repository-merge-manipulation/merge-refs
post /repos/{repo_id}/merges
Merge branch / workspace / commit into target branch
# Apply shelf
Source: https://docs.diversion.dev/api-reference/repository-shelves-manipulation/apply-shelf
post /repos/{repo_id}/shelves/{shelf_id}/apply
Applies a shelf's saved changes to a workspace specified in the `workspace_id` parameter.
**Parameters:**
- `workspace_id` (required)
- `delete_shelf` (optional, defaults to false) - deletes the shelf after successful application
**Conflict handling:**
If conflicts occur during application, returns the merge ID for resolution.
**Returns:**
- `404 Not Found` if the shelf or workspace doesn't exist
- `202 Accepted` with merge_id if conflicts occurred
- `204 No Content` on clean application
# Create a shelf
Source: https://docs.diversion.dev/api-reference/repository-shelves-manipulation/create-a-shelf
post /repos/{repo_id}/shelves
Creates a new shelf by saving the current state of a workspace's uncommitted changes.
**Parameters:**
- `name` (required)
- `workspace_id` (required)
- `reset_workspace` (optional, defaults to true) - clean the workspace after shelving
**Returns:**
- `409 Conflict` if a shelf with the same name exists
- `204 No Content` if the workspace has no changes
- `201 Created` with the shelf details on success
# Delete a shelf
Source: https://docs.diversion.dev/api-reference/repository-shelves-manipulation/delete-a-shelf
delete /repos/{repo_id}/shelves/{shelf_id}
Permanently deletes a shelf and its saved changes.
**Important:**
The shelf cannot be recovered after deletion.
**Requirements:**
Requires WRITE access to the repository.
**Returns:**
- `404 Not Found` if the shelf doesn't exist or the user doesn't own it
- `204 No Content` on successful deletion
# Get shelf details
Source: https://docs.diversion.dev/api-reference/repository-shelves-manipulation/get-shelf-details
get /repos/{repo_id}/shelves/{shelf_id}
Retrieves detailed information about a specific shelf including:
- ID
- Name
- Creation timestamp
- Associated branch ID (if applicable)
- Commit ID
**Requirements:**
Requires READ access to the repository.
**Returns:**
- `404 Not Found` if the shelf doesn't exist or the user doesn't own it
# List shelves
Source: https://docs.diversion.dev/api-reference/repository-shelves-manipulation/list-shelves
get /repos/{repo_id}/shelves
Lists all shelves (saved workspace states) for the current user in a repository, optionally filtered by `branch_id` parameter.
**Each shelf includes:**
- ID
- Name
- Creation timestamp
- Associated branch and commit IDs
**About shelves:**
Shelves allow users to temporarily save uncommitted changes for later reapplication.
**Requirements:**
Requires READ access to the repository.
# Rename a shelf
Source: https://docs.diversion.dev/api-reference/repository-shelves-manipulation/rename-a-shelf
patch /repos/{repo_id}/shelves/{shelf_id}
Renames an existing shelf by updating its name.
**Parameters:**
- `shelf_name` (required) - will be stripped of whitespace
**Requirements:**
Requires WRITE access to the repository.
**Returns:**
- `400 Bad Request` if the name is empty after stripping
- `409 Conflict` if a shelf with the new name already exists
- `204 No Content` on success
# Create a tag
Source: https://docs.diversion.dev/api-reference/repository-tag-manipulation/create-a-tag
post /repos/{repo_id}/tags
Creates a new tag pointing to a specific commit.
**Parameters:**
- `name` (required)
- `commit_id` (required)
- `description` (optional)
**Validation:**
Tag names must be unique within the repository.
**Requirements:**
Requires WRITE access.
**Returns:**
- `409 Conflict` if a tag with the same name exists
- `503 Service Unavailable` if Git sync is in progress
- `201 Created` with the tag ID on success
# Delete a tag
Source: https://docs.diversion.dev/api-reference/repository-tag-manipulation/delete-a-tag
delete /repos/{repo_id}/tags/{tag_id}
Marks a tag as deleted (soft delete).
**Behavior:**
The tag can no longer be retrieved or listed but may remain in the database for audit purposes.
**Requirements:**
Requires WRITE access to the repository.
**Returns:**
- `404 Not Found` if the tag doesn't exist or is already deleted
- `503 Service Unavailable` if Git sync is in progress
- `204 No Content` on successful deletion
# Get tag details
Source: https://docs.diversion.dev/api-reference/repository-tag-manipulation/get-tag-details
get /repos/{repo_id}/tags/{tag_id}
Retrieves detailed information about a specific tag including:
- ID
- Name
- Author (enriched from user database)
- Creation time
- Associated commit ID
- Description
**Requirements:**
Requires READ access to the repository.
**Returns:**
- `404 Not Found` if the tag doesn't exist or has been deleted
# List tags
Source: https://docs.diversion.dev/api-reference/repository-tag-manipulation/list-tags
get /repos/{repo_id}/tags
Lists all non-deleted tags in a repository, including:
- Tag ID
- Name
- Author details (enriched from user database)
- Creation time
- Associated commit ID
- Description
**About tags:**
Tags are lightweight named references to specific commits, useful for marking releases or important milestones.
**Requirements:**
Requires READ access to the repository.
# Update a tag
Source: https://docs.diversion.dev/api-reference/repository-tag-manipulation/update-a-tag
patch /repos/{repo_id}/tags/{tag_id}
Updates tag properties including:
- Name
- Description
- The commit it points to
**Parameters:**
The following optional fields can be provided in the request body:
- `name`
- `description`
- `commit_id`
**Requirements:**
Requires WRITE access to the repository.
**Returns:**
- `409 Conflict` if a tag with the new name already exists
- `400 Bad Request` if the commit doesn't exist
- `204 No Content` on success
# Checkout workspace ref
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/checkout-workspace-ref
post /repos/{repo_id}/workspaces/{workspace_id}/checkout
Set the workspace to follow a different branch or commit (checkout). Currently supports only moving to a branch with an identical commit as the workspace's current branch, or moving to any branch/commit if the workspace has no working changes.
# Cherry-pick commit
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/cherry-pick-commit
post /repos/{repo_id}/workspaces/{workspace_id}/cherry-pick
Cherry-picks changes from a specific commit (identified by `ref_id`) into the current workspace.
**Process:**
- Creates a temporary patch from the source commit
- Applies it to the workspace
- If conflicts occur, returns a merge ID that must be resolved before proceeding
**Requirements:**
Requires WRITE access.
**Returns:**
- `404 Not Found` if the reference doesn't exist
- `202 Accepted` with merge_id if conflicts occurred
- `204 No Content` on clean application
# Copy file into workspace
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/copy-file-into-workspace
post /repos/{repo_id}/workspaces/{workspace_id}/copy_from/{ref_id}/{path}
Copy a file from a ref to the workspace, overwriting any existing file.
# Create a workspace
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/create-a-workspace
post /repos/{repo_id}/workspaces
Create a new workspace with the given name, on the chosen branch or commit. If neither is specified, the default branch is used. If a commit is specified, the workspace will be created on that commit, in a "detached" state, meaning it will not be associated with any branch and new commits cannot be published by it.
# Create draft commit
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/create-draft-commit
post /repos/{repo_id}/workspaces/{workspace_id}/commit-draft
Create a draft commit from workspace changes, optionally with a review
# Delete workspace
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/delete-workspace
delete /repos/{repo_id}/workspaces/{workspace_id}
Deletes a workspace, removing it from the user's workspace list.
**Important:**
The workspace's uncommitted changes are lost unless previously shelved or committed.
**Use cases:**
- Cleaning up unused workspaces
- Switching between different working contexts
**Requirements:**
Requires READ access to the repository.
**Returns:**
- `404 Not Found` if the workspace doesn't exist
- `204 No Content` on successful deletion
# Get workspace details
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/get-workspace-details
get /repos/{repo_id}/workspaces/{workspace_id}
Get a workspace object details.
# Get workspace preferences
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/get-workspace-preferences
get /repos/{repo_id}/workspaces/{workspace_id}/preferences
Retrieves workspace-specific preferences including sync path rules that control which paths are synchronized to the local file system.
**Sync path rules:**
The `sync_paths_rules` array contains glob patterns for selective sync. This enables users to work with large repositories by syncing only relevant subdirectories.
**Requirements:**
Requires READ access to the repository.
**Returns:**
An empty rules array if no preferences are set.
# List workspaces
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/list-workspaces
get /repos/{repo_id}/workspaces
List user's workspaces. Repo owners and admins can optionally list all workspaces in the repo (not just their own) by setting scope=all.
# Merge base branch
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/merge-base-branch
post /repos/{repo_id}/workspaces/{workspace_id}/forward
Fast-forwards a workspace to incorporate the latest changes from its base branch.
**Conflict handling:**
When explicitly requested by users, conflicts are created and returned as a merge ID for manual resolution. This ensures the workspace is up-to-date with the branch before committing.
**Returns:**
- `412 Precondition Failed` if the workspace is detached
- `503 Service Unavailable` if a dependent service is unavailable
- `202 Accepted` with merge_id if conflicts occurred
- `200 OK` if changes were applied
- `204 No Content` if already up-to-date
# Other workspace statuses
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/other-workspace-statuses
get /repos/{repo_id}/workspaces/{workspace_id}/other_statuses
Get list of potential conflicts with files in other users' workspaces and branches
# Reset changes in workspace
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/reset-changes-in-workspace
post /repos/{repo_id}/workspaces/{workspace_id}/reset
Resets uncommitted changes in a workspace by discarding modifications and optionally deleting added files.
**Parameters:**
- `all=true` - reset everything
- `paths` array - reset specific files
- `delete_added` (defaults to false) - controls whether newly added files are deleted
- `write_to_journal` (defaults to true) - records the reset operation
**Returns:**
Lists of:
- Succeeded paths
- Failed paths
- Skipped paths
**Requirements:**
Requires WRITE access.
# Set auto-forwarding status
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/set-auto-forwarding-status
post /repos/{repo_id}/workspaces/{workspace_id}/set_auto_forwarding
Set whether the workspace will automatically advance to the latest commit when its branch receives new commits.
# Update workspace name
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/update-workspace-name
post /repos/{repo_id}/workspaces/{workspace_id}/rename
Renames a workspace to a new name specified in the `name` parameter.
**Validation:**
- The name cannot be empty
- Must be unique for the user within the repository
- Cannot exceed 256 characters
**Requirements:**
Requires READ access to the repository.
**Returns:**
- `400 Bad Request` if the name is invalid (empty or exceeds 256 characters)
- `409 Conflict` if a workspace with the new name already exists
- `204 No Content` on success
# Update workspace preferences
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/update-workspace-preferences
put /repos/{repo_id}/workspaces/{workspace_id}/preferences
Updates workspace preferences, specifically the `sync_paths_rules` array that controls which paths are synchronized.
**Validation:**
New rules are validated to ensure no unselected paths contain uncommitted changes.
**Requirements:**
Requires WRITE access to the repository.
**Returns:**
- `409 Conflict` if attempting to deselect paths with changes (must commit or reset first)
- `202 Accepted` on success
# Workspace status
Source: https://docs.diversion.dev/api-reference/repository-workspace-manipulation/workspace-status
get /repos/{repo_id}/workspaces/{workspace_id}/status
Retrieves the current status of a workspace including:
- Counts of new files
- Counts of modified files
- Counts of deleted files
- Optionally detailed file entries
**Features:**
- Pagination via `limit` and `skip`
- Filtering by `path_prefix`
- Recursive/non-recursive listing via `recurse` parameter
- `detail_items` parameter controls whether full file entries are returned
- Results filtered based on path permissions
- Supports caching and ETags for performance
# Add review comment
Source: https://docs.diversion.dev/api-reference/reviews/add-review-comment
post /repos/{repo_id}/reviews/{review_id}/comments
Add a comment to a review with optional file reference
# Create review
Source: https://docs.diversion.dev/api-reference/reviews/create-review
post /repos/{repo_id}/reviews
Create a new review for comparing two refs
# Get changes for a review
Source: https://docs.diversion.dev/api-reference/reviews/get-changes-for-a-review
get /repos/{repo_id}/reviews/{review_id}/changes
Get the correct ancestor and compare commits for a review.
This endpoint uses the merge commit's parent (if merged) to find the original divergence point,
solving the issue where squash merges make find_common_ancestor return the feature tip.
# Get review
Source: https://docs.diversion.dev/api-reference/reviews/get-review
get /repos/{repo_id}/reviews/{review_id}
Get review details including title, description, and status
# List review comments
Source: https://docs.diversion.dev/api-reference/reviews/list-review-comments
get /repos/{repo_id}/reviews/{review_id}/comments
List all comments associated with a review
# List reviews
Source: https://docs.diversion.dev/api-reference/reviews/list-reviews
get /repos/{repo_id}/reviews
List all reviews for a repository
# Update review
Source: https://docs.diversion.dev/api-reference/reviews/update-review
patch /repos/{repo_id}/reviews/{review_id}
Update review details (title, description, and/or status)
# Update reviewer status
Source: https://docs.diversion.dev/api-reference/reviews/update-reviewer-status
patch /repos/{repo_id}/reviews/{review_id}/reviewers/status
Update the current user's reviewer status for a review
# Get user information
Source: https://docs.diversion.dev/api-reference/user-management/get-user-information
get /user
Retrieves the authenticated user's profile information including:
- User ID
- Email
- Full name
- Avatar URL
- Account tier
**Use case:**
This endpoint provides the current user's details needed for displaying profile information in the client UI.
**Returns:**
- `404 Not Found` if the user doesn't exist in the database (should not occur for authenticated requests)
# Update user information
Source: https://docs.diversion.dev/api-reference/user-management/update-user-information
patch /user
Update user information including display name and email preferences
# Access Levels
Source: https://docs.diversion.dev/basic/access-levels
Understanding the access levels used in granular permissions
Diversion uses a hierarchical access level system to control what users can do in a repository. Each level includes all the permissions of the levels below it.
## Access Level Hierarchy
```
Admin > Write > Merge > Read
```
Each higher level includes all permissions from lower levels. For example, a user with Write access can also Merge and Read.
## What Each Level Can Do
| Level | Description | Operations |
| --------- | ----------------------- | -------------------------------------------------------------------- |
| **Read** | View only | Browse files, view commit history, see diffs, download files, review |
| **Merge** | Accept incoming changes | Accept non-conflicting changes from others during merge operations |
| **Write** | Modify files | Commit changes, resolve merge conflicts |
| **Admin** | Full control | |
## Organization-Level Access
If a repository belongs to an organization, **organization owners and admins are treated as Admin on every repository in that organization** -- even repositories they were never invited to as a collaborator. This applies to every admin-gated operation, not just managing collaborators: things like obliterating files, editing branch protection, granular permissions, webhooks, and auto-lock / auto-release settings are all available to organization owners and admins on any repo in the org.
If their direct repository access is already higher (unusual, since Admin is the top level), it is left as is.
See [Organization Management](/basic/organization-management) for how organization roles are assigned.
## Repository-Level vs Path-Level Access
**Repository-level access** is set when you invite a collaborator. This determines the maximum access level the user can have in the repository.
**Granular permissions access** uses [granular permissions](/basic/granular-permissions) to control access for specific files or folders. For example, you can give someone Write access to the repository but restrict them to Read-only on sensitive paths.
Granular permissions only restrict access - they cannot grant higher access than the user's repository-level permission. Once any granular permission rule exists in the repository, users without matching rules are denied all access by default.
## Choosing the Right Level
| Use Case | Recommended Level |
| ---------------------------------------------------------------- | ----------------- |
| External reviewers or auditors | Read |
| Team members who receive updates but don't directly modify files | Merge |
| Active team members who commit code | Write |
| Team leads and repository owners | Admin |
Start with the minimum access level needed. You can always grant additional access later.
# Branch Protection
Source: https://docs.diversion.dev/basic/branch-protection
Prevent direct commits to important branches and require changes to be merged in
Branch protection lets you safeguard important branches—such as your main branch or release branches—by blocking direct commits. Once a branch is protected, changes can no longer be committed to it directly; they must be made on another branch and merged in.
Branch protection is available to all users at no additional cost.
## What Protection Does
When a branch is protected:
* **Direct commits are blocked.** Users cannot commit changes straight to the protected branch.
* **Changes must be merged in.** To update a protected branch, make your changes on a separate branch and merge that branch into the protected one.
* **Admins can optionally bypass.** You can allow administrators—or a specific list of users—to commit directly, bypassing the protection.
Branch protection currently enforces that changes arrive through a merge. A requirement that merges first pass review or approval is on the roadmap and is **not yet enforced**. This page will be updated when that capability ships.
## Adding a Protection Rule
Check the repository dropdown in the **top-right** of the window and make sure the correct repository is selected before continuing.
Go to **Settings → Branch protection**.
Under **Add branch protection**, open the **Branch** dropdown and choose the branch you want to protect.
Choose who, if anyone, is allowed to commit directly to the protected branch:
* **Allow admins to bypass** — toggle this on to let repository administrators commit directly. When off, the helper text reads *"Admins cannot bypass protection."*
* **Bypass restrictions (optional)** — use the **Select users…** dropdown to add specific users who can bypass protection and commit directly to this branch.
Leave both options untouched to enforce protection for everyone, including admins.
Click **Add protection**. The branch is now protected.
## Managing Existing Rules
Each existing rule lists the protected branch, its bypass status (for example, *"No bypass allowed"*), and any **Allowed users** who can commit directly. Use the **pencil** icon to edit a rule or the **trash** icon to delete it.
### Removing a Protection Rule
To stop protecting a branch, go to **Settings → Branch protection**, find the rule for that branch, and click the **trash** icon to delete it. Direct commits to the branch are allowed again immediately.
# Changing the past
Source: https://docs.diversion.dev/basic/changing-the-past
How to undo, cherry-pick, edit, or copy details from a previous commit
## Undoing a commit
Committed something and wish you hadn't? No worries, you can undo a previous commit with a `revert`. This will create changes that are the opposite of the commit you want to undo.
Open the workspace of the repo where your changes are. Make sure that you have no pending changes. In the left navigation rail, click **Commits**.
Click on the menu icon next to the commit you want to revert, and select "Undo this commit". In the modal window, click "Undo changes". It's possible you'll have to resolve a merge conflict, see below.
You'll see new changes in your workspace that undo the changes for your commit.
In this example, this is the commit I chose to undo:
And this is the resulting change in my workspace:
If you try to revert a commit that affects a file that was also affected by a later commit, it will result in a merge conflict. You'll have to resolve the conflict before you can commit the changes.
Earlier, I reverted a file that was edited. Now, instead, I'll try to revert an earlier commit - the one where the file was created.
This will result in a merge conflict, which you'll have to resolve before you can commit the changes.
## Editing a commit message
Made a typo in your commit message, or want to add more detail? You can edit the message of any commit you authored directly from the Commits view.
Editing commit messages is only available for the commit author, and is not supported for repositories synced with Git.
In the Commits view, click on the menu icon next to the commit whose message you want to change, and select "Edit commit message".
An "Edit commit message" dialog will appear, showing the commit ID for reference and a text area with the current message. Edit the message as you like, then click "Update" to save it.
## Cherry-picking a commit
Cherry-picking lets you take a specific commit from the history and re-apply its changes into your current workspace. This is useful when you want to bring in a particular change without merging an entire branch.
Your workspace must have no uncommitted changes before cherry-picking. Cherry-picking is not available for the initial commit of a repository.
In the Desktop App:
Open the Commits view and find the commit you want to cherry-pick.
Right-click on the commit and select "Cherry-pick into workspace".
If the cherry-picked changes conflict with your current workspace, you'll be taken to the merge conflict resolution view. See [merge conflicts](/basic/working-in-parallel#merge-conflicts) for details on resolving them.
Via the CLI, see the [cherry-pick command](/cmd-ref/cherry-pick) for details.
## Copying commit details
Need to reference a specific commit in a conversation or a script? You can quickly copy a commit's ID or message straight from the Commits view.
In the Commits view, click on the menu icon next to a commit and select "Copy commit ID". The ID is copied to your clipboard right away -- you'll see a "Copied commit ID" notification confirming it.
Similarly, you can select "Copy commit message" from the same menu to copy the full commit message text to your clipboard.
# Draft Commits
Source: https://docs.diversion.dev/basic/draft-commits
Request feedback on your changes before committing them
## What are Draft Commits?
Draft commits let you request feedback on your changes **before** they're committed to your active branch. You can create a review directly from your uncommitted workspace changes.
This keeps your commit history clean while still getting the code review you need.
## Why Use Draft Commits?
Draft commits are ideal when you:
* **Work on a single branch** and want a simpler review workflow
* **Want early feedback** on work-in-progress changes before finalizing them
* **Keep your history clean** by only committing approved changes
* **Experiment with ideas** and want team input before making them permanent
Draft commits are optional. You can still use the regular commit workflow if you prefer to commit first and review later.
## Draft Commits vs Reviews
Here's a quick comparison to help you choose the right workflow:
| | Draft Commits | Reviews |
| ------------------ | ------------------------------------------- | --------------------------------------------- |
| **When to use** | Get feedback before committing | Get feedback on existing commits/branches |
| **Starting point** | Uncommitted workspace changes | Committed changes in a branch |
| **Commit history** | Changes only committed after approval | Changes already in branch history |
| **Workflow** | Edit → Send to review → Approve → Commit | Commit → Create review → Approve → Merge |
| **Best for** | Single-branch workflow, work-in-progress | Multi-branch workflow, feature branches |
| **Commit history** | Only approved changes committed | May include intermediate/experimental commits |
| **Flexibility** | Easy to discard or modify before committing | Requires reverting or amending commits |
Both features create the same review experience with comments, approvals, and notifications. The main difference is **when** you commit your changes - before or after getting feedback.
## Creating a Draft Commit
**Step-by-Step Instructions:**
1. **Make changes in your workspace**
* Edit files as you normally would
* Your changes remain uncommitted in your workspace
2. **Open your repository**
* Open your repository in the Diversion web app
* Your workspace's pending changes appear in the **Files** view
3. **Click the dropdown arrow next to "Commit..."**
* The commit button has a dropdown arrow (▼) on the right side
* Click the arrow to open the dropdown menu
* Select **"Send to review\..."**
4. **Confirm the files to send**
* A confirmation dialog shows the files that will be sent to review
* Review the file list and click **"Send to review"** to proceed
5. **Fill in the review details**
* **Title** (required): Brief description of your changes
* Example: "Add user authentication endpoints"
* **Description** (optional): Detailed explanation for reviewers
* Explain what you changed and why
* Mention any areas where you need specific feedback
* **Reviewers** (optional): Select teammates who should review your changes
* You can add reviewers now or later
6. **Click "Send to Review"**
* A review is automatically created with your uncommitted changes
* Your workspace is automatically cleared so you can immediately continue working on other changes (the changes are safely stored in the draft)
* Assigned reviewers receive email notifications
## Managing Your Draft Commits
### Viewing Your Drafts
1. **Open the branch selector**
* Open the branch selector (top-left, showing the current branch and commit), then click the **Drafts** tab.
2. **Find your drafts**
* Your draft commits appear under the **Drafts** tab
* Each draft shows its title and source branch
3. **Access draft actions**
* Click the **...** (more options) menu next to a draft to see available actions:
* **View Review**: Open the associated review to see feedback and comments
* **Update**: Switch to the draft to continue working on it
* **Close**: Discard the draft commit
You can have multiple draft commits open simultaneously, allowing you to work on different changes and get feedback on each independently.
## Updating a Draft Commit
If you need to make changes to your draft after creating it:
**Step-by-Step Instructions:**
1. **Find your draft**
* Open the branch selector and switch to the **Drafts** tab. Locate your draft in the list.
2. **Click "Update"**
* Click the **...** (more options) menu next to your draft
* Select **"Update"** from the menu
* Confirm by clicking **"Switch to draft"** in the dialog
* This switches your workspace to the draft branch and loads the draft changes
* You can now continue editing
3. **Make additional changes**
* Edit files to address reviewer feedback
4. **Update the draft**
* Commit your changes
* The review updates automatically with your new changes
* Reviewers see the updated diff
## After Review Approval
Once your reviewers have approved your draft:
1. **Review the feedback**
* Read through all comments and approvals
* Make sure all concerns are addressed
2. **Finalize your changes**
* Switch back to the draft if needed to make final adjustments
* Ensure everything is ready to commit
3. **Commit the changes**
* The approved changes can now be committed to your branch
* Your commit history stays clean with only reviewed, approved changes
4. **The draft closes automatically**
* Once merged or committed, the draft status changes to closed
## Closing a Draft Commit
If you decide you don't want to proceed with a draft:
**Step-by-Step Instructions:**
1. **Find your draft**
* Open the branch selector and switch to the **Drafts** tab. Locate your draft in the list.
2. **Click "Close"**
* Click the **...** (more options) menu next to your draft
* Select **"Close"** from the menu
3. **Confirm closing**
* Click **"Close draft"** in the confirmation dialog
* This action cannot be undone
4. **Draft is removed**
* The draft is deleted from your active drafts list
* If you were on the draft branch, you are switched back to the source branch
* Changes are discarded
## Working with Draft Reviews
### Review Process
Draft commits create reviews automatically, so the review process works the same:
* **Reviewers can comment** on specific lines or files
* **Reviewers can approve or request changes**
* **You receive notifications** when reviewers respond
* **Discussion happens in the review** just like regular reviews
For detailed review instructions, see the [Reviews documentation](/basic/reviews).
### Notifications
You'll receive email notifications for:
* When reviewers comment on your draft
* When reviewers approve or request changes
* When the review is closed/merged
# The .dvignore file
Source: https://docs.diversion.dev/basic/dvignore
Safely ignore files not needed in your repository
The `.dvignore` file is used by Diversion to specify files and directories that should be ignored when tracking changes. This helps keep the repository clean by excluding unnecessary or automatically generated files, such as build artifacts, temporary files, and cached data.
### Purpose
Using a `.dvignore` file ensures that only relevant files are committed to the repository. This helps:
* Prevent clutter from unnecessary files.
* Improve performance by avoiding tracking large or frequently changing temporary files.
* Avoid committing sensitive or auto-generated files.
While `.dvignore` decides what the repository **tracks and stores**, [Selective Sync](../advanced/selective-sync) controls which of those already‑tracked files your workspace actually downloads.
### File Structure
The `.dvignore` file consists of patterns defining which files or directories to exclude. It typically follows these rules:
* A line starting with `#` serves as a comment. Put a backslash `\` in front of the first hash for patterns that begin with a hash.
* Don’t mix comments and patterns on the same line. **Mixing them will cause the pattern to not have any effect.**
* Wildcard `*` matches any sequence of characters (but does **not** cross `/` boundaries, unlike `**`).
* Directories ending with `/` ignore all contents inside.
* Negations `(!)` explicitly include files that might otherwise be ignored.
#### Advanced rule semantics
* **Root‑anchored `/`** – a leading slash matches from the repository root; without it, the pattern can match anywhere.
* **Double asterisk `**`** – matches across directory boundaries (e.g., `Assets/**/config.ini`).
* **Negation precedence** – a `!pattern` only re‑includes a path if one of its ancestors was ignored by a prior rule.
```text theme={null}
Saved/*
!Content/**
```
`Saved/Windows/Content/file.txt` -> still ignored
* **Nested `.dvignore` files** – rules in nested directories override rules from parent directories.
> **Git compatibility**: Diversion implements the same pattern‑matching semantics as Git’s `.gitignore`—including support for nested ignore files—so a source tree copied from Git will behave identically out of the box.
IMPORTANT NOTE: Diversion treats existing .gitignore files (both root and nested) similarly to .dvignore files, so when a Git repository is transferred into Diversion its original ignore rules are preserved.
When both .dvignore and .gitignore exist in the same directory, their patterns are merged and .dvignore takes precedence (last-match-wins). This lets you override .gitignore rules without editing the .gitignore itself.
In some cases, such as transferring the Unreal Engine source repository from Git, you may want to remove the existing .gitignore files
and replace them with a custom ignore file tailored to your needs.
#### Enabling the V1 matcher
Ignore-file matching in Diversion is versioned. The default works well for most projects, and **V1** is an opt-in upgrade whose pattern matching follows Git's `.gitignore` rules even more closely — last-matching-rule-wins precedence, negations that re-include paths, root-anchored patterns, `**` across directory boundaries, and nested ignore files. To turn it on, add this directive as the **first non-empty line** of your repository-root `.dvignore`, before any patterns (leading blank lines are fine):
```
# dv-ignore-version: 1
```
If the directive is missing or isn't on the first non-empty line, Diversion keeps using the default matcher.
For game‑engine projects Diversion ships a default **.dvignore** tailored to each engine. The snippets below are high‑level illustrations; check the actual **.dvignore** generated in your repo for the authoritative rules.
#### Unreal
```
# Unreal Engine build files
Build/*
# Saved game states and config files
Saved/*
# Compiled intermediate files
Intermediate/*
# Editor cache files
DerivedDataCache/*
```
#### Unity
```
# Unity temp folder
.utmp/
# Unity Library
/[Ll]ibrary/
# Temporary files
/[Tt]emp/
# Object files
/[Oo]bj/
# Build directories
/[Bb]uild/
/[Bb]uilds/
# Log files
/[Ll]ogs/
# User-specific settings
/[Uu]ser[Ss]ettings/
# Memory captures
/[Mm]emoryCaptures/
# Recordings
/[Rr]ecordings/
```
For the complete Unity `.dvignore` with IDE files, Addressables, Visual Scripting, and more, see [Unity Best Practices](/unity/unity-best-practices).
#### Godot
```
# Godot internal directory
.godot/
# Import cache folder
.import/
# Export settings
export.cfg
# Export presets
export_presets.cfg
# Auto-generated translation files
*.translation
```
You can modify the `.dvignore` file based on your project needs. If you work with additional tools or frameworks, consider adding their cache or temporary directories to improve repository management.
For example, if you use a custom build system, you might add:
```
/build_output/
/temp_build_files/
```
### Ignoring already committed files
IMPORTANT NOTE: Files and directories that are already committed, will NOT be ignored by .dvignore.
1. If you wish to ignore a committed path, you need to first delete it and commit the deletion. If the content of that path can’t be auto-generated, you should back it up somewhere else and copy back after committing the deletion.
2. Notify your collaborators to backup their copies before committing the deletion, because updating with that commit will delete their copies too.
3. Example of auto-generated paths: build artifacts and intermediates, auto-generated code.
4. Example of non-auto-generated paths: credentials files, local configuration files.
An empty directory will NOT be ignored if there is a **negation** rule for one of its descendants.
When a directory has a **negation** rule for one of its descendants, Diversion keeps that directory **tracked**, even if the descendant file doesn’t exist yet.
```
Build/*
!Build/app.dll
```
Because `!Build/app.dll` re-includes a possible future file, the `Build/` directory itself is tracked (and will show up empty until `app.dll` appears).
If you really want to ignore `Build/` altogether, remove the negation line (`!Build/app.dll`).
# Get an existing project
Source: https://docs.diversion.dev/basic/get-existing-project
Clone a repo and manage files in your workspace
A team member has [set up Diversion](/basic/start-using-diversion) for your project and [invited you to join](/basic/manage-project-access),
or maybe you want to get your own project that you created on another computer. Let's get you set up:
Open the repo's `...` menu and select `Clone repo`.
A new folder with the repo's name will be created in it (here - `DiversionExample`).
Click `Clone`.
The project should start downloading right away. When it's done, you can open it and start working!
## File operations
Diversion gives you quick access to common file operations right from the Files view. Right-click any file to see the available actions, or use the file title bar when viewing a file.
### Delete a file
In the Files view, right-click on the file you want to delete and select **Delete**.
You'll see a confirmation dialog asking "Are you sure you want to delete the file '\[file-path]'?" Click the red **Delete** button to confirm, or cancel if you changed your mind.
The deleted file will appear in your pending changes in **red** with an **x** icon, indicating it has been deleted.
For CLI usage, see the [rm command](/cmd-ref/rm).
### Rename a file
In the Files view, right-click on the file you want to rename and select **Rename**.
A dialog appears with the current file name pre-filled. Type the new name for your file.
Click **Rename** to apply the new name.
Don't forget to include the file extension in the new name (e.g. `.txt`, `.cpp`, `.uasset`). Omitting it may cause the file to become unrecognized by your OS or game engine.File names cannot contain any of these characters: `< > : " / \ | ? *`
The renamed file will appear in your pending changes in **green** with a **double arrow (>>)** icon, indicating a move/rename operation.
For CLI usage, see the [mv command](/cmd-ref/mv).
### Move a file
In the Files view, right-click on the file you want to move and select **Move**.
A directory picker dialog opens. Browse to the folder where you want to move the file.
Click **Move** to move the file to the selected folder. The file keeps its original name.
The moved file will appear in your pending changes in **green** with a **double arrow (>>)** icon, indicating a move/rename operation.
For CLI usage, see the [mv command](/cmd-ref/mv).
### View file history
In the Files view, right-click on the file and select **History**.
The file history page shows all commits that changed this file, including the operation type (added, modified, moved), commit message, author, and date for each change. Click on any commit to see the diff for that version.
### Restore a previous version
When viewing a file at a specific commit, you can send that version to your workspace. This replaces the current file contents with the selected version, and the change appears in your pending changes.
You can get there in two ways:
* From the **file history**: right-click a file, select **History**, then click on the commit you want.
* From the **branch history**: open a commit, then click on the file you want to restore.
In the file title bar, click the **Send this version to workspace** button (arrow icon).
The restored file will appear in your pending changes as a modification. You can review the changes and commit when ready.
For CLI usage, see the [restore command](/cmd-ref/restore).
### Annotate (blame)
The **Annotate** view shows who last modified each line of a file, along with the commit message and date. This is useful for understanding how a file evolved and who is responsible for specific changes.
Annotate is only available for text files. Binary files are not supported.
Right-click a file in the Files view and select **History**.
Click the **Annotate** tab at the top of the file history view.
The left panel shows a color-coded dot, how long ago the change was made, the author name, and the commit message for each line range. The right panel shows the file contents with line numbers.
Hover over any entry in the left panel to see full commit details: author avatar and name, date, full commit message, and commit ID. Click **View commit** to navigate to that commit.
For CLI usage, see the [annotate command](/cmd-ref/annotate).
### Download a file
When you click on a file in the workspace or commit view, a download icon button appears in the file title bar. Click it to download the file to your computer.
### Open in Explorer (Desktop only)
Right-click a file in the Files view and select **Show in Explorer** (Windows) or **Reveal in Finder** (macOS) to open the containing folder in your system file explorer.
This option is only available for locally cloned workspaces. Make sure the Diversion agent is running.
This is also useful for opening project files directly. For example, you can use **Show in Explorer** to navigate to your Unreal Engine `.uproject` file and open it from there.
### Open with default app (Desktop only)
When viewing a file, click the **Open with default app** icon in the file title bar to open the file with whatever application your OS associates with that file type.
This option is only available for locally cloned workspaces. Make sure the Diversion agent is running.
You can also use this to open project files directly -- for example, opening a `.uproject` file will launch it in Unreal Engine. Keep in mind that you may need to have previously opened the project with the correct engine version for this to work as expected.
# Going back in time
Source: https://docs.diversion.dev/basic/going-back-in-time
Reverting to or branching from a previous commit
You've been working on your project for a while, and you realize that you made a mistake a few commits ago. Or maybe you want to start a new feature based on an older version of your project. No worries! You can go back in time to a previous commit.
## Reverting to a previous commit
One way to go back in time is to revert to a previous commit. This will create changes in your workspace that undo all of the commits from the commit you've chosen to revert to up to the current commit. This does not create a new commit!
Since this action will automatically create changes in your workspace, it must be clean beforehand. Undo or commit any changes you have.
In the **Commits** view, click the menu for the commit you want to revert to and select `Revert to this commit`.
You'll be taken to the **Files** view where you'll see the changes that will be made.
## Branching from a previous commit
Another way to go back in time is to create a new branch from a previous commit. This will create a new branch with the commit you've chosen as the base.
Follow the steps to create a new branch, as described in [Working in parallel](/basic/working-in-parallel#creating-a-new-branch).
# Granular Permissions
Source: https://docs.diversion.dev/basic/granular-permissions
Control access to specific paths within your repository
Granular permissions allow you to set fine-grained access control for specific files and folders within a repository. Instead of giving users full repository access, you can restrict what they can read, write, merge, or administrate at the path level.
## When to Use Granular Permissions
Granular permissions are useful when you need to:
* **Protect sensitive paths**: Prevent team members from modifying security-critical code, configuration files, or production assets
* **Restrict by role**: Allow designers to only modify assets while developers work on code
* **Isolate components**: Let teams work on specific parts of the repository without accessing others
## Access Levels
Diversion uses four hierarchical access levels:
| Level | Description |
| --------- | ----------------------------------- |
| **Admin** | Full control |
| **Write** | Can modify files |
| **Merge** | Can participate in merge operations |
| **Read** | Can view files only |
Access levels are hierarchical: Admin includes all privileges of Write, which includes Merge, which includes Read. See [Access Levels](/basic/access-levels) for details on what each level can do.
## Permission Types
Each rule uses one of four permission types that control how access is granted or denied:
| Type | Behavior |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Allow (Hierarchical)** | Grants the specified level **and all lower levels**. Example: Allow (Hierarchical) + Write grants Write and Read access. |
| **Allow (Exact)** | Grants **only the exact level** specified. Example: Allow (Exact) + Write grants Write but not Read. |
| **Deny (All Above)** | Stops rule evaluation and denies all access levels (the level field is ignored). Any permissions already granted by higher-priority rules (lower in table) are kept. |
| **Deny (Exact)** | Denies **only the exact level** specified. Example: Deny (Exact) + Write denies Write but allows Read. |
Use **Allow (Hierarchical)** for most cases since it grants natural permission inheritance. Use **Exact** types when you need to grant or deny a specific level without affecting others (e.g., deny Write but keep Read).
## Path Patterns
Path patterns specify which files a rule applies to. Patterns always start with `/` representing the repository root.
| Wildcard | Behavior |
| -------- | --------------------------------------------- |
| `*` | Matches within a single directory only |
| `...` | Matches recursively across all subdirectories |
Here are some common patterns:
| Pattern | Matches |
| ------------------- | --------------------------------------------------- |
| `/path/to/file.txt` | Exact file match |
| `/path/...` | All files under `/path/` recursively |
| `/path/....py` | All `.py` files under `/path/` recursively |
| `/path/*` | All files directly in `/path/` (not subdirectories) |
| `/path/prefix*` | Files in `/path/` starting with "prefix" |
## Rule Priority
Rules are evaluated from the **bottom of the table to the top**. When multiple rules match, the **highest permission wins** - unless a Deny rule stops evaluation.
Rules lower in the table have **higher priority**. Deny rules can override Allow rules above them.
### Example: Multiple Allow Rules
| # | User | Path | Level | Type |
| - | ----- | --------------- | ----- | -------------------- |
| 1 | alice | /src/... | Write | Allow (Hierarchical) |
| 2 | alice | /src/secret/... | Read | Allow (Hierarchical) |
When Alice accesses `/src/secret/config.json`:
* Both rules match
* The highest permission (Write) is granted
* **Result: Alice can Write** to files in `/src/secret/`
### Example: Using Deny to Restrict Access
| # | User | Path | Level | Type |
| - | ----- | --------------- | ----- | -------------------- |
| 1 | alice | /src/... | Write | Allow (Hierarchical) |
| 2 | alice | /src/secret/... | Write | Deny (All Above) |
When Alice tries to access `/src/secret/config.json`:
1. Rule 2 matches first (bottom, highest priority) - stops evaluation and denies all access
2. Rule 1 is never evaluated
3. **Result: Alice has no access** to files in `/src/secret/`
**Deny (All Above)** is a terminal rule. When it matches, evaluation stops immediately - no more rules above it are checked. Any permissions already granted by higher-priority rules (lower in the table) are kept.
You can reorder rules in the UI by dragging them to change their priority.
## Assigning Permissions
Permissions can be assigned to:
* **Individual users** - Apply rules to specific team members
* **Groups** - Apply rules to all members of a group (requires an organization). Prefer groups over individual users - it keeps permissions easier to maintain as your team grows.
Each rule must target either a user or a group, not both. Create separate rules if you need to apply the same pattern to both.
## Setting Up Granular Permissions
Click your **profile avatar** in the top navigation and select **Your profile**.
Select **Permission Rules** under the Repositories section in the sidebar.
Select the repository you want to configure.
Click "Edit Table" to enable editing mode.
Click "Add Rule" and configure:
* **User or Group**: Who this rule applies to
* **Path Pattern**: Which files are affected
* **Access Level**: Admin, Write, Merge, or Read
* **Permission Type**: How to apply the access level
You can reorder rules by dragging them (rules at the bottom have higher priority), edit any field, or delete rules you no longer need.
## Evaluation Logic
When a user tries to access a file:
1. Find all rules matching the file path for the user (including their groups)
2. Evaluate rules from bottom to top (highest priority first)
3. For each rule:
* If **Deny (All Above)** matches the requested level: Stop evaluating (previously granted permissions are kept)
* If **Deny (Exact)** matches exactly: Mark exact level as denied, continue evaluating
* If **Allow (Hierarchical)** or **Allow (Exact)** matches: Mark as granted, continue
4. Final decision: The highest granted permission wins, unless a deny was recorded
**Default behavior:**
* If there are **no granular permission rules** in the repository, users get their repository-level permission.
* Once **any rule exists** for any user, users without matching rules are **denied all access**. Make sure to add rules for all users who need access.
## API Access
You can manage granular permissions programmatically using the [Granular Permissions API](/api-reference/repository-granular-permissions/list-granular-permissions).
# Import from Git
Source: https://docs.diversion.dev/basic/import-from-git
How to get an existing repo from Git into Diversion
Importing an existing repo from Git can get you quickly up and running with Diversion.
You can also enable bi-directional sync between your Git repo and Diversion, so that
changes made in either place are reflected in the other.
This is a great way to take Diversion for a test drive with no commitment.
To import a repo using the Web UI, follow these steps:
Go to the [Diversion Sync GitHub App page](https://github.com/apps/diversion-sync) and follow the instructions to install it.
Go to [your Dashboard](https://app.diversion.dev/dashboard), open the repo selector dropdown (top-left), and choose **Import Git repository** from its footer (alongside **Create new repository** and **Import from Perforce**).
Choose whether you want to import your entire repo and keep all of its history, or just the latest commit from a specific branch.
If you choose to `Import all branches with history`, you'll have the option to `Enable continuous bi-directional sync`.
If you need bi-directional sync, please contact us at [support@diversion.dev](mailto:support@diversion.dev).
This happens in the background, and depending on the size of your Git repo can take a few minutes.
You will receive an email when the import is complete.
To import a repo using the CLI, follow these steps:
Go to the [Diversion Sync GitHub App page](https://github.com/apps/diversion-sync) and follow the instructions to install it.
Open your terminal of choice.
If you want an interactive shell with nicer UI, open your terminal of choice and run the `dv` command.
It works the same as your regular terminal, and you can use any of the `dv` commands (`commit`, `init`, etc...) directly without prefacing them with `dv`.
Run the following command:
```bash theme={null}
dv import [git_url]
```
This will start importing your repo into Diversion with the default name - the same as the repo's name in Git.
There are several optional arguments for the `import` command. You can always run `dv help import` to see them in the terminal.
Passing a repo name to the `import command` will save the repo to Diversion with that name, instead of the repo's name in Git.
```bash theme={null}
dv import [git_url] [repo-name]
```
Enables bi-directional sync between your new Diverson repo and your Git repo. This means that any change you make to one repo will be reflected in the other.
This is useful for testing Diversion or for keeping any Git-based pipelines you have in place.
```bash theme={null}
dv import [git_url] --with-sync
```
If you need bi-directional sync, please contact us at [support@diversion.dev](mailto:support@diversion.dev).
By default, Diversion will import the latest commit from the default branch of your Git repo. If you want to import the latest commit from a different branch, you can use the `--git-branch` flag.
```bash theme={null}
dv import [git_url] --git-branch [branch-name]
```
By default, Diversion will only import the latest commit from the default branch of your Git repo. If you want to import the entire repo with all of its history, you can use the `--with-history` flag.
```bash theme={null}
dv import [git_url] --with-history
```
This happens in the background, and depending on the size of your Git repo can take a few minutes.
You will receive an email when the import is complete.
# Import from Git LFS
Source: https://docs.diversion.dev/basic/import-from-git-lfs
How to get an existing repo that uses Git LFS into Diversion
Importing an existing repo from Git with LFS configured is very similar to importing a regular Git repo, with a few
small differences that will be explained below.
## Importing a Git LFS repo
The basic steps to import a Git LFS repo are the same as importing a regular Git repo.
See the [Import from Git](/basic/import-from-git) page for more information.
## Considerations for Git LFS
When importing a Git LFS repo, there are a few things to keep in mind:
### Supported storage backend
Diversion currently only supports Github as a storage backend for Git LFS. If your files are hosted on a different
Git LFS storage backend, please [contact us](https://www.diversion.dev/contact-us), drop in
our [Discord server](https://discord.com/invite/HDAGJvgkuT) or [email us](mailto:hi@diversion.dev).
### Export to Git LFS
When bidirectional sync is turned on, all files will be pushed to your Git repo, including files that are configured
to be stored in Git LFS. This means that if you have a large number of files in your Diversion repo, you might hit
the storage limits of your Git repo provider. To avoid this, consider importing without bidirectional sync.
### Cost considerations for initial import
When importing a Git LFS repo, the files in the LFS storage will be downloaded to your Diversion repo. This might be
counted against your LFS bandwidth quota, depending on your Git LFS storage provider.
### Cost considerations for bidirectional sync
If you choose to continuously sync your Diversion repo with your Git LFS repo, keep in mind that your Git storage
costs might increase, as you add more files to your Diversion repo. Consult with your Git repo
provider's pricing for cost estimation. To minimize costs, consider disabling bidirectional sync.
### Performance considerations for bidirectional sync
There is a key difference between how Diversion works and how Git LFS works. Diversion continuously syncs your files
to the cloud, while Git uploads files only when you push changes. This means that if you have a large number of files
to commit in your Diversion repo, with bidirectional sync turned OFF the operation is usually instantaneous - the files
are usually already in the cloud by the time you commit them. With bidirectional sync turned ON, the files will have
to be pushed to your Git repo first, which might take a while. This is a server-to-server operation, so it might
still be faster than pushing the files from your local machine, but it's something to keep in mind.
# Invoices and billing
Source: https://docs.diversion.dev/basic/invoices
Access your invoices, update payment methods, and manage your subscription
All billing and invoicing in Diversion is managed through our billing portal. From there you can view and download invoices, update your payment method, and adjust your subscription.
Only organization owners can access the billing portal. If you're a team member, ask your organization owner for invoice copies.
## Accessing the billing portal
Click on your avatar in the top navigation and select **Plan & Billing**.
You'll be redirected to the billing portal where you can:
* View and download past invoices and receipts
* Update your payment method
* View your current subscription details
* Adjust user seats and storage
## Downloading an invoice
In the billing portal, locate the invoice you need in the invoice history section. Click on the invoice to view its details, then use the download or print option to save a copy.
## Managing your payment methods
In the billing portal, find the payment method section and click **Add payment method** to add your credit card or other payment method.
You cannot remove your default payment method while you have an active plan. To change it, add a new payment method and set it as default first, then remove the old one.
## Canceling your subscription
Click on your avatar in the top navigation and select **Plan & Billing** to open the billing portal.
Under **Current subscription**, click **Cancel subscription**.
Cancellation takes effect at the end of your current billing period, so you keep access to your plan until then. You can re-subscribe at any time from **Plan & Billing**.
## Need help?
If you have questions about billing, need a refund, or require a custom invoice, [contact our billing team](mailto:billing@diversion.dev).
For information about available plans and pricing, see [choosing your plan](/choosing-your-plan) or visit our [pricing page](https://www.diversion.dev/pricing).
# Manage project access
Source: https://docs.diversion.dev/basic/manage-project-access
Manage repo collaborators: add, remove, and leave repositories
## Add people to your project
You have a project set up, and want to add your team members? Here's how:
Open the repository's **...** menu - in its row on either the **Local Workspaces** or **Remote Repositories** tab of the dashboard, or from the open repository's actions menu - and select **Collaborators**.
If you don't have a repo yet, [create one first](/basic/start-using-diversion).
Also choose the access level you want to grant. Admins can invite other members.
That's it! Your team members will receive invitation emails to join the project. If they don't have Diversion installed yet, they'll be prompted to do so.
They can accept the invitation and start working with you. The repo appears on the **Remote Repositories** tab in the app -- they open its `...` menu and select `Clone repo` to get started. If they need any help, [send them here](/basic/get-existing-project).
## Remove people from your project
Open the repository's **...** menu - in its row on either the **Local Workspaces** or **Remote Repositories** tab of the dashboard, or from the open repository's actions menu - and select **Collaborators**.
Click on the user's permission level and select **Delete**.
Only repo owners and admins can remove members. The repo owner cannot be removed.
Review and confirm your action.
**Good to know:**
* Removing a member from a repo doesn't remove them from the organization (if applicable)
* You can re-invite removed members at any time
* Removed members will immediately lose access to the repo and its contents
* Their local files on disk are not deleted
## Leave a repository
**Good to know:**
* Leaving a repo doesn't remove you from the organization (if applicable)
* You can be re-invited at any time
* You will immediately lose access to the repo and its contents upon leaving
* Your local files on disk are not deleted
* You cannot leave a repo you own
There are two ways to leave a repository:
### Option 1: From the repository's collaborators dialog
Open the repository's **...** menu - in its row on either the **Local Workspaces** or **Remote Repositories** tab of the dashboard, or from the open repository's actions menu - and select **Collaborators**.
Click on your permission level and select **Delete**.
### Option 2: From the remote repo
Review and confirm your action.
## Transfer repository ownership
To transfer repository ownership, the repository must be associated with an organization. For detailed instructions, see [transferring repository ownership](/basic/organization-management#transferring-repository-ownership) within the same organization, or [transferring a repository to another organization](/basic/organization-management#transferring-a-repository-to-another-organization) across organizations.
## FAQs
### Why am I receiving system messages about exceeding my user limit when my repository has fewer users?
If you're seeing [system messages](/system-messages) like this:
Even after removing excess users from all your repositories, check your organization members. The excess users may still be part of your organization and need to be removed there as well. See [removing users from your organization](/basic/organization-management#removing-users) for detailed instructions.
# Organization management
Source: https://docs.diversion.dev/basic/organization-management
Managing your organization, its members, and repositories
In Diversion, an organization is a group of users who share repositories, making it easier to collaborate and manage projects. You can find your organizations under `Your organizations` in the user menu.
## Creating an organization
You can only create one organization per account, but you can be a member of many organizations.
### Creating your first organization
**If you don't own or belong to any organization:**
1. Click on your avatar in the top navigation and select `Create organization`.
2. Choose a name for your organization and click `Create organization`.
**If you already belong to one or more organizations:**
Create the new organization from the New Repository dialog: click the `Parent organization` dropdown and select `+ Create New Organization`, then enter your organization name. See [Creating an organization while creating a repository](#creating-an-organization-while-creating-a-repository) below.
### Creating an organization while creating a repository
Alternatively, you can create an organization while creating a new repository:
1. When creating a new repository, click the `Parent organization` dropdown and select `+ Create New Organization`.
2. Enter your organization name to create both the repository and organization simultaneously.
**Note:** As an organization owner, you are responsible for all billing, including storage usage and organization member seats. When you upgrade to a paid tier, an organization may be created automatically for you depending on your tier (Indie/Educational/Professional).
## Managing an organization
Each organization has an owner. The owner can invite other users to join the organization.
When you add a user to your organization, they won't have access to all of your repositories and you can still manage access on a per-repo basis.
When inviting a user, the owner can decide if the user should have admin privileges. Admins can also manage users, same as the owner.
The difference between the owner and an admin is that billing for the organization is managed through the owner's Diversion account.
If you send an invite to someone who doesn't have a Diversion account, they will be prompted to create one.
### Removing users
The owner or admins can also remove users from the organization. When removing a user, you'll be prompted with the list of repositories the user can access. These are all of the repositories that the user will no longer have access to.
This means that the Diversion agent will no longer sync these repositories with the user's workspace. This also means that the user will keep stale copies of the repositories that were previously cloned locally.
Removing a user that owns repositories is currently not supported through the app. You'll have to contact support to transfer ownership of those repositories before removing the user.
## Working in an organization
Every repository belongs to an organization. When you create a new repository, you set its `Parent organization` in the create dialog: if you belong to a single organization it is used automatically, and if you belong to more than one you choose which one to use. If you don't belong to any organization yet, a personal organization is created for you automatically and the repository is placed in it. This ensures that all repositories are properly organized and accessible to the relevant team members.
Other than that, working as part of an organization is exactly the same as working as an individual user.
## Attaching a repository to an organization
If you own a repository that isn't part of any organization, you can attach it to an organization you own at any time, directly from the dashboard, without contacting support. (New repositories are always created within an organization, so this applies to older repositories that predate that behavior.)
The `Attach to Organization` action is available when all of the following are true:
* You are the **owner** of the repository.
* The repository is **not** already part of an organization.
On your dashboard, open the **Remote Repositories** tab and look under **Personal** -- repositories that aren't part of an organization appear there, not under **Local Workspaces**. Find the repository's row, click its **...** menu, and select `Attach to Organization`.
In the `Attach Repository to Organization` dialog, choose the destination organization from the `Select Organization` dropdown. Only organizations you own are listed.
The dialog then previews which repository collaborators (and pending invitees) are not yet members of the selected organization. Attaching the repository will add them as members of the organization, counting toward its user quota. If everyone is already a member, the dialog confirms that no users will be added.
Click `Attach to Organization` (or `Attach and Add N Users` when collaborators will be added) to complete the action. The repository, along with its storage usage, now belongs to the organization.
You must be the owner of an organization to attach a repository to it. If you don't own any organization, [create one first](#creating-an-organization).
## Organization repository management
Organization owners and admins can view and manage all repositories associated with the organization, including repositories they are not personally collaborating on. This includes managing collaborators and transferring ownership.
### Viewing organization repositories
Click on your avatar in the top navigation and select `Your organizations`. The organization whose settings you see is controlled by the organization selector in the top-left of the global bar; use it to pick the organization you want.
In the left sidebar, click `Repositories` to view all repositories in the organization.
You will see a table listing all repositories in the organization, including their name, creation date, size, auto-update status, and collaborators. As an organization owner or admin, you can see repositories that you are not personally collaborating on.
If you belong to multiple organizations, use the organization selector in the top-left of the global bar to switch between organizations.
### Managing repository collaborators
Organization owners and admins can manage collaborators for any repository in the organization, even if they are not a collaborator on that repository themselves.
Go to your organization's Repositories page as described above.
Find the desired repository in the table and click the menu icon on the right side.
Click `Manage Collaborators` to open the collaborators dialog.
From the collaborators dialog, you can:
* View all current collaborators and their permission levels
* Invite new collaborators by entering their email address and selecting an access level
* Change a collaborator's permission level
* Remove a collaborator from the repository
* Add yourself to the repository by entering your own email address — even if you're not currently a collaborator on that repo
### Transferring repository ownership
You can transfer repository ownership to another member of the organization. The user performing the transfer must be both the repository owner and an organization admin or owner.
Go to the `Repositories` page in your organization page (accessible from the left sidebar).
Find the desired repository. Click on the menu icon on the right side and select `Transfer ownership`.
Choose the member you wish to transfer ownership to from the dropdown and confirm the transfer.
This action cannot be undone. The new owner will have full control over the repository, and you will lose ownership privileges.
### Transferring a repository to another organization
You can transfer a repository from your organization to another organization. Only the **owner of the source organization** can initiate the transfer. The destination organization owner must approve the request before the repository moves.
If you are a repository owner but not the source organization's owner, ask your organization owner to initiate the transfer on your behalf.
Open the source organization's `Repositories` page. If you belong to multiple organizations, use the organization selector in the top-left of the global bar to switch to the source organization first. Find the desired repository, click the menu icon on the right side, and select `Transfer Organization`.
Type the email address of the destination organization's owner and click `Send Request`. A transfer request is sent to that email and appears on the destination owner's dashboard.
The destination organization owner has **14 days** to accept or decline the request. You will be notified by email when they respond. If the request is not approved within 14 days, it expires automatically and the repository remains in your organization.
This action is irreversible. Once accepted, the repository is permanently moved out of your organization. All repository members who are not already members of the destination organization will be added to it — counting toward the destination organization's user quota — and the repository's storage will count toward the destination organization's storage quota.
If you need to remove a repository from your organization but there is no destination organization to send it to — for example, the repository's owner is no longer active and you simply want the repository gone — [contact support](mailto:support@diversion.dev).
#### Reviewing an incoming transfer request
If another organization's owner sends you a transfer request, you will be notified by email and an `Incoming repository transfer` card will appear on your dashboard.
Find the `Transfer of [repository name]` card in the pending invites section of your dashboard and click `Review...`.
The review dialog shows the source organization, the repository's storage size, the members that will be added to your organization, and when the request expires.
Click `Accept Transfer` to move the repository into your organization, or `Decline` to reject the request. The initiator is notified by email either way.
Transfer requests expire after 14 days. Expired requests cannot be accepted — the source organization owner must send a new request.
## Leaving an organization
Only non-owner members can leave an organization. Switch to the organization you wish to leave using the organization selector in the top-left of the global bar, then open its settings and click "Leave organization".
**Note:** Leaving an organization will result in losing access to all repositories associated with it. You can always be invited back to the organization later.
If you own one or more repositories that are associated with the organization, you won't be able to leave the organization. You must either [transfer the repository ownership](#transferring-repository-ownership) to another member of the organization or delete the repositories first.
## Organization deletion
Deleting an organization is not possible. If you no longer need an organization, you can remove all members and repositories from it.
## FAQs
### What happens to my repositories if I'm a member of multiple organizations?
Every repository is created within an organization. If you belong to more than one organization, you choose its `Parent organization` in the create dialog; if you belong to a single organization, that one is used; and if you don't belong to any, a personal organization is created for you automatically. A repository is therefore never left unassigned at creation time. Older repositories that aren't part of any organization can be [attached to one](#attaching-a-repository-to-an-organization) you own.
### How do I transfer organization ownership to another user?
Ownership transfer is currently handled by our support team. If you're an organization owner and want to transfer ownership:
1. Ensure the new owner is already a member of your organization. If not, invite them first as explained above.
2. Email our support team with your request, including the new owner's email address, and our team will complete the transfer.
3. The new owner should select their desired tier, storage capacity, and seats, then add a payment method to avoid subscription breach [system messages](/system-messages).
4. Once the new owner has set up their subscription, cancel your old subscription from **Plan & Billing** to avoid double payment.
### How do I become the owner of an organization I am a member of?
Ask your organization owner to contact our support team and request the ownership transfer to your account. The owner should follow the steps outlined in the question above.
### Why am I receiving system messages about exceeding my user limit?
If you're seeing [system messages](/system-messages) like this:
This means your organization has more members than your current plan allows. To resolve this, you have two options:
1. **Upgrade your plan** - Purchase additional user seats to accommodate your current team size.
2. **Remove users from your organization** - See the [removing users](#removing-users) section above for step-by-step instructions.
If you're seeing [system messages](/system-messages) like this:
This means you haven't selected a plan yet. To resolve this:
**Select a plan** - See [choosing your plan](/choosing-your-plan) for guidance, or visit our [pricing page](https://www.diversion.dev/pricing) to view available options.
### How do I move repositories out of my organization?
As the organization's owner, you can transfer any repository in your organization — even ones you don't personally own or collaborate on — using the [Transfer Organization](#transferring-a-repository-to-another-organization) action. Send each request to the email of the owner of the destination organization.
### How do I move my repositories from another organization to my own?
Ask the current organization's owner to use the [Transfer Organization](#transferring-a-repository-to-another-organization) action on the repository and submit the request to your email address. Once you accept the request from your dashboard, the repository moves into your organization.
# Repository management
Source: https://docs.diversion.dev/basic/repo-management
Rename, delete, and manage your Diversion repositories and workspaces
## Renaming a repository
Only the repository owner can rename a repository.
Go to the **Remote Repositories** tab on the dashboard (not from a local workspace). Locate the repository you want to rename.
Click the **...** menu on the repo's row and select **Rename**.
In the **Rename Repository** dialog, type the new name for your repository and click **Rename**.
## Deleting a repository
Deleting a repository is permanent and cannot be undone. All branches, commits, and history will be lost.
Go to the **Remote Repositories** tab on the dashboard (not from a local workspace). Locate the repository you want to delete.
Click the **...** menu on the repo's row and select **Delete**.
To prevent accidental deletion, you must type the exact repository name to confirm. Then click **Delete**.
Via the CLI, run `dv repo -d `. See the [repo command](/cmd-ref/repo) for details.
Your local files on disk are not deleted -- only the cloud repository is removed. The local folder stops syncing and can be moved or deleted manually.
## Viewing workspaces
If you are an owner or admin of a repository, you can view and manage all workspaces in that repository, including those belonging to other collaborators. This is useful for debugging issues or managing changes on behalf of a team member.
Click on your avatar in the top navigation and select **Your profile**.
In the left sidebar under **Repositories**, click **Workspaces**. If you are an owner or admin of multiple repositories, use the repository selector dropdown to pick the repository you want to inspect.
The table lists all workspaces with their name, auto-update status, and owner. Click the actions menu on a workspace and select **Open** to view its contents and pending changes. You can also **Rename** or **Delete** workspaces from this menu.
When you open a workspace you don't own, any operations you perform will affect the workspace owner. A confirmation dialog will appear before you proceed.
# Reviews
Source: https://docs.diversion.dev/basic/reviews
Code reviews in Diversion
## What are Reviews?
Code reviews in Diversion let you request feedback on your changes before merging them into your main branch. Team members can review your code, leave comments, approve changes, or request modifications.
## How Reviews Work
A review compares two refs (branches or commits) in your repository:
* Base ref: The target where changes will be merged (usually main)
* Compare ref: The branch or commit containing your changes
When you create a review, Diversion calculates the differences between these two refs and presents them to your team for feedback.
## Creating a Review
There are two ways to create a review in Diversion:
### Method 1: Create Review from Branch (Most Common)
Use this when you want to compare two branches and get feedback before merging.
**Step-by-Step Instructions:**
1. **Navigate to Reviews section**
* Open your repository in Diversion web app
* Click on the **"Reviews"** icon in the left navigation rail
2. **Click "Create new review" button**
3. **Select branches to compare**
* **Base branch**: Select the branch you want to merge INTO (usually main)
* Click the dropdown under "Base branch"
* Choose your target branch (e.g., `master`, `main`, `develop`)
* **Compare branch**: Select the branch WITH your changes
* Click the dropdown under "Compare branch", or start typing to search for a branch
* Choose your feature branch (e.g., `feature/user-dashboard`)
4. **Fill in review details**
* **Title** (required): Short description of your changes
* Example: "Add user authentication system"
* **Description** (optional): Detailed explanation
* Explain WHY you made these changes
* Mention any important context
5. **Add reviewers** (optional)
* Click the "Reviewers" dropdown
* Select one or more teammates who should review your changes
* You can skip this and add reviewers later
6. **Click "Create review"**
* The review will be created immediately
* Assigned reviewers will receive email notifications
* You'll be taken to the review page
### Method 2: Create Review from Merge Dialog
Use this when you're ready to merge but need approval first
**Step-by-Step Instructions:**
1. **Navigate to the branch you want to merge**
* Go to the **"Branches"** section in Diversion web app
* Find your feature branch (the one WITH your changes) in the Branches list
* Click on that branch and choose the merge direction
* Notes: You cannot merge the branch you're currently on. You must click on a different branch to see merge options
2. **Choose "Create review request"**
* A dialog appears asking how you want to proceed
* You'll see several options, including:
* **"Create review request"**: Request review before merging
* **"Preview merge"**: See merge diff without creating review
* (The dialog also offers **"Merge now"** and **"Cancel"**.)
* Click **"Create review request"**
* If a review already exists for these branches, click "Go to review requests"
3. **Fill in review details**
* If a review already exists for these branches, it will take you there
* Otherwise, you'll see the review creation form
* The base and compare branches are already filled in
* Add title, description, and reviewers
* Click **"Create review"**
### What You Need for All Methods
Every review requires:
* **Base branch**: Where you want to merge your changes (e.g., `master`)
* **Compare branch**: The branch with your changes
* **Title**: A clear, concise description (required)
* **Description**: More detailed explanation (optional but recommended)
* **Reviewers**: Teammates who should review (optional, can add later)
## Reviewing Someone's Changes
### When You're Asked to Review
You'll get an email notification when someone requests your review.
**Step-by-Step Instructions:**
1. **Open the review**
* Click the link in your email notification, OR
* Go to Diversion web app → **"Reviews"** section
* Find the review in the list (you'll see your name as a reviewer)
* You can filter reviews by status (Open, Closed) and by whether they're your reviews
* Click on the review to open
2. **Look at the review details**
* At the top, you'll see:
* Review title and description
* Who created the review
* Which branches/commits are being compared
* Current status and other reviewers
3. **Review the changes**
* You'll see two tabs:
* **"Conversation"**: Shows all comments and discussion
* **"Files Changed"**: Shows the code diff
* Click **"Files Changed"** to see what code changed
4. **Leave comments** (explained below)
* Add general comments about the overall changes
* Add inline comments on specific lines of code
5. **Make your decision**
* Go to the **"Files Changed"** tab
* Click **"Review changes"**
* Choose one of these options:
* **"Approve"**: Changes look good, ready to merge
* **"Request Changes"**: Something needs to be fixed
* Add an optional comment to explain your decision
* Click the **"Submit review"** to submit your decision
6. **Done!**
* The review author receives notification of your decision
* Your review status will be updated and appear both in the conversation and on your avatar under the "Reviewers" section
### Adding Comments
#### General Comments
Use general comments for big-picture feedback about the whole review.
**How to add a general comment:**
1. Open the review page
2. Go to the **"Conversation"** tab
3. Scroll to the comment box at the bottom
4. Type your comment
5. Click **"Comment"** button
**How to reply to a comment:**
1. Find the comment you want to reply to in the **"Conversation"** tab
2. Type your response
3. Click **"Reply"** to post your reply
**Examples of general comments:**
* "The overall approach looks great!"
* "Have you considered how this handles edge cases?"
* "This needs unit tests before we can merge"
* "Great work on the error handling!"
#### Inline Comments
Use inline comments to point out specific issues in particular lines of code.
**How to add an inline comment:**
1. Open the review page
2. Go to the **"Files Changed"** tab
3. Find the file you want to comment on
4. **Click the line number** in the diff view
5. A comment box appears on the right side of the screen
6. Type your comment about that specific line
7. Click **"Comment"** button
**How to add a file-level comment:**
1. Open the review page
2. Go to the **"Files Changed"** tab
3. Find the file you want to comment on
4. Click the **"+"** button above the changed version of the file
5. A comment box appears on the right side of the screen
6. Type your comment about the entire file
7. Click **"Comment"** button
**Examples of inline comments:**
* "This function should handle the case where user is null"
* "Consider using a constant here instead of magic number"
* "Great improvement over the previous version!"
* "This could cause a race condition if called concurrently"
### Viewing Review Status
**Your status as a reviewer:**
* **REQUESTED**: You haven't responded yet - review is waiting for you
* **APPROVED**: You approved the changes
* **CHANGES REQUESTED**: You requested modifications
**The review's overall status:**
* **OPEN** (blue): Review is active, may still need approvals
* **MERGED** (purple): Changes were approved and merged
* **CLOSED** (gray): Review was closed without merging
## Editing Review Details
After creating a review, you can edit the title and description by clicking the pencil icon next to them, or edit reviewers by clicking the settings icon next to the reviewers section.
## Working with Review Feedback
### When Changes Are Requested
1. Read through all the comments carefully
2. Make the requested changes on your branch
3. Commit the fixes (they'll automatically show up in the review)
4. Reply to comments to explain what you changed
5. Ask reviewers to take another look
### Updating Your Branch
If you're using a branch review, any new commits you push will automatically appear in the review. Reviewers will see:
* All your original changes
* Any new commits you added to address feedback
* The complete, updated diff
### When You Get Approvals
Once all reviewers have approved (or enough approvals based on your team's policy):
1. Do a final check that everything looks good
2. Click the **"Merge review"** button on the review page to merge the changes
3. The review status will automatically change to MERGED
## Notifications
You'll get email notifications for:
* When someone requests your review
* When someone comments on your review
* When reviewers approve or request changes
* When a review is merged or closed
All notifications include a link to view the review in Diversion.
# Shelves
Source: https://docs.diversion.dev/basic/shelves
Save workspace changes temporarily and manage your shelves
In Diversion, you can shelve your current work and apply it later when switching back to the original branch.
This works similarly to the "stash" mechanism in Git.
## When to use shelves
* **Switching context:** Save work-in-progress before switching to another branch
* **Experimenting:** Try out changes without committing, easily revert if the experiment doesn't work
* **Working across machines:** Shelve changes on one computer and apply them on another. Shelves are stored in the cloud per repository, so they are available from any workspace on the same repo.
## Creating a shelf
Use the shelf button in your workspace to create a shelf.
1. Select the files you want to shelve in your workspace
2. Click **Shelve...** to open the naming dialog:
3. [Name](#naming-your-shelf) your shelf
4. Click **Create shelf**
### Automatic shelves
When switching branches with uncommitted changes, a popup menu will ask what to do with them.
Select **Save changes for later use** to create an automatic shelf.
### Naming your shelf
When creating a shelf, you can:
* Enter a custom name (max 60 characters)
* Click **Generate name** to create a name like `my_branch (2025-01-13 13:00:00)`
Shelf names must be unique within your repository.
## Managing shelves
Open the branch selector and switch to the **Shelves** tab to view and manage your shelves.
### Preview
Click on a shelf to preview its contents before applying.
### Apply
Click **Apply** to restore the shelved changes to your workspace.
If the shelved changes conflict with your current workspace, you'll need to resolve the conflicts before continuing.
### Rename
Click **Rename** to change the shelf name.
### Delete
Click **Delete** to permanently remove a shelf. This action cannot be undone.
***
For CLI usage, see the [shelf](../cmd-ref/shelf) command reference.
# Start using Diversion in your project
Source: https://docs.diversion.dev/basic/start-using-diversion
Create a new Diversion repo for a completely new project or an existing one
You're working on a project. How exciting!
What you want is a Diversion repository. Let's get you set up:
You can do this with [our Unreal Engine plugin](/unreal/unreal-engine-plugin)!
In the desktop app, click on the `New repository` button on the top right.
You can create a new folder or use an existing one. If you have a game-engine project, you probably want to choose its root folder.
For this example I'll create a new folder, but the other steps work the same either way.
I'll select `Create New Folder`and call it `CreatingNewRepo`.
A new repo is created in the folder you specified! The workspace's **Sync** toggle shows it's syncing - the status text reads something like "Syncing: Scan in progress" while it uploads the folder's content to our cloud.
In this example it's an empty folder so it should only take a moment. If you create a new repo for an existing project, it might take a bit longer.
Once the sync status shows the workspace is fully synced, you're all set!
And that's it! You have a new repository. Anything you do in the directory will be tracked by Diversion.
If there are files you don't want tracked (e.g. build artifacts, temporary files), you can use a [.dvignore file](/basic/dvignore) to exclude them.
## What's next?
* [Manage project access](/basic/manage-project-access) — invite collaborators to your repo
# Pause/Resume sync
Source: https://docs.diversion.dev/basic/sync-pause-resume
Pause and resume your background sync
Diversion's agent keeps you up to date with the latest changes in your repos by syncing them in the background. Whenever you save a change, it's automatically uploaded to your workspace and you're always backed-up.
### Auto-pause
In some error cases, such as network issues, the agent will automatically pause syncing. You can continue working normally. When committing, make sure your sync is active so you commit the most recent changes.
To resume the sync through the desktop app, turn the **Sync** toggle back on for the workspace -- on its row in the dashboard's **Local Workspaces** tab, or via the sync status pill in the repo sub-header ("Sync paused / click here to resume"). You can also run the `dv workspace resume` command in the repo's folder through the CLI.
### Manual Pause/Resume
You might not want to be auto-synced, for example if you're making many small changes in a very large file, or if you're on a slow network connection.
In order to pause sync for a workspace, you first need to have it fully synced, like in the image below. Turn off the **Sync** toggle on the workspace row to pause. Resuming the sync is done in the same way mentioned above.
# Undo pending changes
Source: https://docs.diversion.dev/basic/undo-pending-changes
Undo changes you haven't committed yet
Changed your mind? Are you unhappy with your most recent work? Let's undo changes you haven't committed yet. In Diversion, this is called `reset`, and will return the files to state they were in the last commit.
Open the workspace of the repo where your changes are. In the **Files** view, you'll see a list of files with changes.
Use the checkboxes next to the files, or can select all with the checkbox at the top. Once you have selected the files, click the red **Reset** button at the top right of the file list.
You'll see a confirmation dialog. Keep in mind that by default, this only undoes changes to existing files and does not delete new files. If you want to delete new files, click on the "Delete new files" checkbox.
# What to do with your changes
Source: https://docs.diversion.dev/basic/what-to-do-with-your-changes
Commit or reset changes in your repo
You've made some changes to your project - created new files, modified existing ones, or deleted some. Now what?
You can do this with [our Unreal Engine plugin](/unreal/unreal-engine-plugin)!
## Review your changes
In the desktop app, go to your repo. In the **Files** view, you should see the files you've changed.
Each change is marked with an icon and a color. You can always hover over the icon to see what change was made - added, modified, deleted, or moved (which includes renaming).
The buttons on the top let you change the way you see your list of changes. Choose one you like.
When you click on a file you changed, if it's in a supported format, it will open in the main panel. Right now Diversion supports text files and images.
Use the button on the top to switch to `Diff View` to see the changes you made.
## Commit your changes
If you like your changes and want to keep them, you should `Commit` them. A commit is like a snapshot of your project at a certain point in time. It's an encapsulated unit of change in your repository.
When you commit your changes, any collaborators you have in your project will be able to see them.
If your collaborators are on the same branch as your are, assuming they have no conflicting changes, the changes you commit will be automatically synced to their workspaces.
For more info, check out the [Branches](/concepts/repo-branch-workspace) page.
To commit your changes, choose which files you want to include in the commit, write an informative commit message, and click `Commit`.
You can choose to commit all changes, using the checkbox above the list, or only some of them.
You should try to keep your commits small and focused, and your commit messages should be descriptive and informative. Remember, even if you're working alone - Future You will thank you for it.
When you're ready, hit the commit button! Your changes are now saved in your repository. The `Commit...` button also has a split dropdown that offers `Send to review...` and `Shelve...` if you'd rather request feedback or set the changes aside instead.
## Undo your changes
If you don't like your changes and want to undo them, you can `Reset` them. This will revert the files to the state they were in when you last committed them.
You can reset files using the red `Reset` button on the top right. Using this method you can reset multiple files at once.
Alternatively, you can reset individual files using the file's context menu.
By default, when resetting changes, any new files you've added won't be deleted. If you want to delete new files, make sure to check the `Delete new files` checkbox in the confirmation dialog.
# Working in parallel
Source: https://docs.diversion.dev/basic/working-in-parallel
Branching and merging
You want to work on a project with your team, but you don't want to step on each other's toes.
No worries! There's a way to work on your project in parallel without interfering with each other's work, and then recombine it all together when you're done.
It's called branching and merging.
## Branching
You can think of a branch as a separate version of your project.
When you create a branch, you're creating a copy of your project at that point in time.
### Creating a new branch
In the Desktop App:
Open the branch selector at the top-left of the repo view and click **+ New branch**.
Give your branch a name that describes what you're working on.
Also, pay attention to the commit you're branching from - this will be the base for our new branch.
You can automatically switch to the new branch after creating it by leaving the checkbox checked, it's checked by default.
Via the CLI, see the [branch command](/cmd-ref/branch) for creating branches and more options.
### Switching branches
In the Desktop App, the branch selector at the top-left shows your current branch. Click it to see all branches in the repository under the **Branches** tab (the default branch is marked with a home icon).
Clicking on another branch lets you view it in read-only mode without switching.
To switch, click the menu for the branch you want and select "Switch to branch".
If you have any changes in your workspace that you haven't committed, you can choose to discard them, [shelve](/basic/shelves) them for later, or take them with you to the new branch, if possible (see [Merge conflicts](#merge-conflicts) below).
Via the CLI, see the [checkout command](/cmd-ref/checkout) for switching branches.
Switching a branch changes the files on your computer. For some game engines, like Unreal Engine, you might need to restart the editor to see the changes.
### Branch graph
You can see a visual graph of all your branches and commits in the Desktop App.
Click **Graph** in the left navigation rail.
The graph shows an interactive visualization of all branches and commits. You can pan and zoom to navigate around the graph.
Right-click on any commit or branch in the graph to open its context menu. From here you can access the same actions available elsewhere -- create a branch, cherry-pick a commit, merge, and more.
If you have a lot of branches, this is a great way to understand how they relate to each other.
### Important things to remember
1. Working on any branch is just like working on your main branch. Making changes, committing, syncing - it's all the same.
2. Branches are visible to anyone in your repo, and anyone can switch to any branch.
3. The committed changes on the branch are only available to team members who are on the same branch.
4. There is no need to pull or fetch. When a teammate commits to a branch you're on, your workspace is updated automatically. See [syncing](/concepts/syncing) for more details on how auto-update works and how to control it.
### Managing branches
#### Delete a branch
If you no longer need a branch, you can delete it. Note that you cannot delete the default branch.
In the Desktop App, in the branch list, right-click (or click the menu icon) on the branch you want to delete and select "Delete".
**What happens when you delete the branch you're currently on?** If you delete the branch you are currently viewing, you will be redirected to the repository's main page. Any workspaces that were checked out to the deleted branch will remain in a **detached state** -- they keep their current files and uncommitted changes, but are no longer associated with any branch. To continue working, switch to another branch from the workspace.
Via the CLI, see the [branch command](/cmd-ref/branch) for deleting branches and more options.
#### Rename a branch
You can rename a branch from the Desktop App. This is not supported for repositories synced with Git.
In the branch list, right-click (or click the menu icon) on the branch you want to rename and select "Rename". Type the new name and click "Rename".
Via the CLI, see the [branch command](/cmd-ref/branch) for renaming branches.
#### Set the default branch
The default branch is the branch that new workspaces are based on when they are created. Only admins can change the default branch, and this option is only available in the Desktop App.
In the branch list, right-click (or click the menu icon) on the branch you want to set as default and select "Set as default branch". This option is only visible if you are an admin of the repository.
There is no CLI equivalent for this action.
## Merging
When you're done working on your branch, you can merge it back into your main branch.
Merging takes all of the changes from one branch and applies them to another.
### How to merge
In the Desktop App, open the branch selector, find the branch you want to merge on the **Branches** tab, and choose the merge option from its menu.
If there are no conflicts, you should see a new merge commit in your branch history.
Via the CLI, see the [merge command](/cmd-ref/merge) for merging branches.
### Merge conflicts
Sometimes, the changes you made on your branch conflict with the changes someone else made on another branch.
When you try to merge these branches together, you'll have to decide how to handle these conflicting changes.
In the Desktop App, if you have conflicting changes and follow the steps in [How to merge](#how-to-merge), you'll see a screen that shows you the conflicting files instead of the successful merge commit.
The conflict window has 4 parts:
1. A list of files with conflicting changes.
2. For each file on the list:
1. The incoming file. This is a readonly version of the file that's on the branch you're trying to merge from.
2. The current file. This is a readonly version of the file that's on the branch you're trying to merge into.
3. The outcome file. This is what the file will look like after you resolve the conflict. This is editable.
To resolve a conflict, you need to decide which changes to keep and which to discard. You can choose either the incoming version, the current version, or a combination of both.
And, as mentioned above, you can edit the outcome file directly.
If you want to make the same choice for many files, you can select them using their checkboxes and use the buttons at the bottom.
When you're done, type a commit message and hit 'Commit'.
For resolving merge conflicts via the CLI, see [Handling Merge Conflicts (CLI)](/core-concepts/branching-merging#handling-merge-conflicts).
#### Merging non-text files
Non-text files, like images, 3d models, spritesheets, animations, etc., can't be merged. This merge process works because text files are human-readable and can be compared line by line.
If you have a merge conflict with a non-text file you have 2 options:
1. If you have a specific tool that can merge these files, you can use it to resolve the conflict. One example is [Unreal Engine's built-in merge tool](/unreal/ue-plugin-merge-conflicts)
which you can use if you have [our plugin](/unreal/unreal-engine-plugin).
2. Choose one version to keep and discard the other.
### Merge conflict warning
Diversion has a feature that warns you about files that are being edited by other team members, and might cause a merge conflict.
If you see the merge warning icon on a file, you can click on it and get info about who's editing the file. Be sure to communicate before working on it to prevent merge conflicts.
As mentioned above, this is crucial when working on non-text files.
#### Why is the warning icon showing on many files?
The warning icon reflects files that are currently modified (uncommitted) in any workspace on the repo, not just the one you are looking at -- whether it belongs to a collaborator or is another one of your own. If you see it on a large number of files at once, the usual cause is that one of those workspaces is holding a lot of uncommitted changes. Every modified file there gets flagged for everyone on the branch.
The warning does not name the workspace that holds the changes, but clicking the icon shows which user is editing the file. To track it down, that user should review each of their own [workspaces](/basic/workspace-management) for uncommitted changes, or a repository owner/admin can review all workspaces in the repo owned by that user (see [Viewing workspaces](/basic/repo-management#viewing-workspaces)). Once found, commit or revert the changes in that workspace, or delete it if it is no longer needed.
# Workspace management
Source: https://docs.diversion.dev/basic/workspace-management
Create, rename, delete, and clone workspaces
Every collaborator on a repository gets their own workspace -- a private space where you can make changes without affecting anyone else. Workspaces keep your uncommitted work separate and synced to the cloud automatically.
If you're not familiar with the concept, check out the [Repositories, Branches, and Workspaces](/concepts/repo-branch-workspace) page first.
We recommend using a separate workspace for each machine. Cloning the same workspace on multiple machines may lead to sync issues and data loss.
## Cloned vs. non-cloned workspaces
A workspace can be either **cloned** (local) or **non-cloned** (cloud-only). Understanding the difference helps you decide how to set up your workflow.
| | Cloned (local) | Non-cloned (cloud-only) |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| **Where files live** | On your machine, synced with the cloud | Only on the Diversion cloud |
| **How to edit files** | Use any local editor, IDE, or game engine | Upload files through the web or desktop app |
| **Auto-sync** | Changes sync bidirectionally -- local edits upload automatically, and remote changes download automatically | No local sync needed -- everything is already in the cloud |
| **Show in Explorer / Finder** | Available -- opens the file's location on disk | Not available |
| **Open with default app** | Available -- opens the file with your OS's associated application | Not available |
| **Disk usage** | Uses local disk space for the full working copy | No local disk space used |
**When to use a cloned workspace:** Most of the time. If you're actively developing -- writing code, editing assets in a game engine, or using any local tools -- you need a cloned workspace so those tools can access the files on disk.
**When to use a non-cloned workspace:** When you only need to browse files, review changes, or manage branches without editing locally. This is useful for lightweight access from a machine where you don't want to download the full project, or for managing multiple workspaces without duplicating large repositories on disk.
You can clone a non-cloned workspace at any time -- see [Cloning a workspace locally](#cloning-a-workspace-locally-desktop-only) below.
## Creating a new workspace
In the Desktop App:
Open the workspace selector at the top-right of the repo view.
This opens the **Create New Workspace** dialog.
Give your workspace a descriptive name. This is required.
In the desktop app, you can also check the **Clone this workspace locally** option to immediately create a local copy. If you choose to clone, you'll need to pick a folder name and a directory on your machine.
The workspace is created from the repository's default branch. Once it's ready, you'll be navigated to the new workspace automatically.
For CLI usage, see [clone command](/cmd-ref/clone).
## Working from multiple computers
You can work on the same project from several machines -- a desktop and a laptop, for example. Set up a separate workspace on each machine rather than sharing one.
Your machines stay in sync through commits. **Uncommitted local changes stay on the machine where they were saved** -- they are not uploaded to the cloud or visible from any other computer until you commit them. Once committed, every workspace tracking that branch picks them up automatically. To move *uncommitted* work between machines without committing, use [Shelves](/basic/shelves), which are stored in the cloud and available from any workspace on the same repository.
Don't share a single workspace between machines via a cloud-synced folder (Dropbox, OneDrive, iCloud, Google Drive), a network drive, or by copying the `.diversion` directory. Each machine's agent will fight over the workspace's state, which can cause files to be deleted, sync loops, or repeated `dv reset` recoveries.
### Set up a second machine
Sign in with the same account you use on your primary machine.
Follow the [Creating a new workspace](#creating-a-new-workspace) steps and clone it locally. Give it a name that identifies the machine (e.g., `main-laptop`) so you can tell your workspaces apart.
Your new workspace syncs automatically. See [Moving work between your machines](#moving-work-between-your-machines) below for how changes travel from one machine to the other.
### Moving work between your machines
Work travels between your machines through commits:
* **Commit on the machine you're working on.** Only committed changes upload to the cloud, and only while sync is active -- so commit your work (`dv commit -a -m "message"` or the desktop app) and make sure sync isn't paused.
* **Find the changes on the branch they were committed to.** Each commit lands on a branch, and a workspace shows only the commits on the branch it's currently on. To see changes you made on another machine, open the **branch selector** in the desktop app (or run `dv checkout `) and switch to the branch they were committed to.
* **Let the workspace update.** With [auto-update](/concepts/syncing#workspace-automatic-update) on, the workspace pulls new commits automatically -- just like a teammate's workspace would. With it off, the sync status shows **Pending workspace updates** -- click it, or run `dv update`.
* **Selective Sync decides what lands on disk.** A folder left unchecked under **Settings -> Selective Sync** won't download locally even when its files are committed. See [Selective Sync](/advanced/selective-sync).
## Workspaces on external storage
You can keep a cloned workspace on a USB drive, external SSD, or other detachable drive that mounts as a regular local disk. This lets you carry a workspace between machines without re-cloning, as long as each machine has Diversion installed and you're signed in with the same account.
When cloning, pick a folder on the external drive as the local location.
With the drive connected and the Diversion agent running, the workspace syncs normally.
If the workspace doesn't appear after you plug the drive back in -- or after you connect it to a different machine -- use [Attach workspace](#attaching-a-workspace-desktop-only) to point Diversion at the workspace folder on the drive.
## Renaming a workspace
Click your avatar and select **Your profile** (or **Your organizations**), then under **Repositories** in the left sidebar click **Workspaces**. Find the workspace, click the actions menu at the end of its row, and select **Rename**.
The **Rename Workspace** dialog shows the current name pre-filled. Type in the new name you'd like.
The button is disabled if the name is empty or unchanged, so make sure you've actually typed something different.
You can also rename a workspace from the workspace selector on the repo view: open the selector, click the **...** (more options) menu next to the workspace, and select **Rename**.
For CLI usage, see [workspace command](/cmd-ref/workspace).
## Deleting a workspace
Click your avatar and select **Your profile** (or **Your organizations**), then under **Repositories** in the left sidebar click **Workspaces**. Find the workspace, click the actions menu at the end of its row, and select **Delete**.
The **Delete Workspace** dialog asks you to confirm. Keep in mind that all uncommitted changes in the workspace will be lost.
If the workspace is cloned locally, you'll see an additional warning that your local files will remain on disk but will no longer sync with Diversion. You'll need to check a confirmation checkbox before proceeding.
This action is permanent -- the workspace and any uncommitted changes are gone for good.
You can also delete a workspace from the workspace selector on the repo view: open the selector, click the **...** (more options) menu next to the workspace, and select **Delete**.
For CLI usage, see [workspace command](/cmd-ref/workspace).
## Cloning a workspace locally (Desktop only)
If you have a workspace that isn't cloned to your machine yet, you can set up a local synced copy at any time.
Open the workspace selector at the top-right of the repo view. Workspaces that aren't cloned on this machine appear under **Remote**. Select the one you want to clone locally.
A directory picker opens -- choose where you want the local copy to live on your machine.
Diversion creates a local copy and keeps it synced automatically. Any changes you make locally will be reflected in the cloud workspace, and vice versa.
For CLI usage, see [clone command](/cmd-ref/clone).
## Attaching a workspace (Desktop only)
If you moved a repository to a different path on your machine, or if a workspace is not showing up after detaching a portable drive, you can re-attach it to Diversion.
On the dashboard, click the **Attach workspace** button in the toolbar.
A directory picker opens. Navigate to the folder containing your workspace (the folder with a `.diversion` directory inside it).
Diversion will look up the workspace on the server and reconnect it. You'll see a confirmation message once the workspace is successfully re-attached.
The workspace folder contains a hidden `.diversion` directory that Diversion uses to track workspace state. This folder must remain in place and should not be modified or deleted. To verify it exists, enable hidden files in your file explorer (on Windows: View > Show > Hidden items; on macOS: press Cmd+Shift+.). If it is missing, or if the workspace was deleted from the server or you don't have permission to access it, you'll see an error message.
## Change the folder name without re-cloning
You can change the folder name without re-cloning by following these steps:
This is the workspace we will use for the example:
Right-click the Diversion icon in your system tray and select *Quit*, or end the dv.exe task in the Task Manager.
Option a:
Option b:
Change the folder name directly in your file explorer.
Run the command dv in your command line and verify it starts successfully. Alternatively, open the desktop app and click "start agent" when prompted.
Option a:
Verify:
Option b:
Since the folder was renamed, the workspace will not be displayed. Click *Attach workspace*.
Navigate to the path with the new folder name and click *Connect*.
You should now be able to see your workspace:
# Choosing Your Plan
Source: https://docs.diversion.dev/choosing-your-plan
Choose and manage Diversion's subscription plans
For detailed information about Diversion's available plans, visit our [pricing page](https://www.diversion.dev/pricing).
## How do I select a tier?
You can select a tier if you haven't yet selected one and meet one of the following criteria:
* You are an organization owner
* You are not a member of any organization
**Note:** If you are an organization member but not the owner and wish to select a tier, you can [create an organization](/basic/organization-management).
### Steps to select a tier
1. Click on your avatar and select **Plan & Billing**
2. Select your desired tier. For Educational and Indie tiers, you'll be directed to a form to verify your eligibility.
3. After selecting your tier, navigate back to **Plan & Billing** to add users and storage space. You'll be redirected to the billing page where you can adjust these settings.
## How do I change my tier?
To change your tier, contact our [support team](mailto:support@diversion.dev) with your request:
* **Professional tier:** Our support team will assist you with the upgrade process.
* **Educational tier:** Provide an updated enrollment letter from your educational institution.
* **Indie tier:** Provide a short description of your project along with your request.
Once your request is approved, you can select the new tier following the steps above. For Indie and Educational tiers, you'll need to complete an eligibility form.
## My trial has ended, what's next?
After your trial ends, you need to select a tier. Until you do:
* You and your team can continue using Professional tier features
* You'll receive [system messages](/system-messages) about plan limitations
* Eventually, you'll lose write access to your resources (unable to commit)
To maintain full access, select a tier as soon as possible.
## I'm not the organization owner, but I keep receiving plan [system messages](/system-messages). What should I do?
Only organization owners can select tiers and manage subscriptions. Contact your organization owner and ask them to:
* Select an appropriate tier for the organization
* Update the current subscription if needed
## I submitted an Indie/Educational tier application. When will it be approved?
The approval process typically takes about one week. During this period:
* You can use the tier you selected
* Ensure all required files and information are uploaded
* If your request is denied, our team will contact you within a week
If you don't hear from us after a week, your request has been approved.
Our team may move users to a different tier if they no longer meet the Indie/Educational terms agreed to in the form. We'll always notify you before making any changes.
## Indie form FAQ
### Company
No worries — just state your current work status. For example: Unemployed, Freelance, or Part-time at \[Name of Company].
That's completely fine, just state it as-is. Your current occupation won't affect your submission or its approval.
This helps us confirm the Indie plan is the right fit. It's designed for independent creators and small teams, so we use this context to keep it fair for everyone.
### LinkedIn URL
No problem — you can submit a link to any social profile related to your game development project instead (e.g., Twitter/X, itch.io, GitHub, etc.).
We use it to verify that the details you've provided match your profile. It's a quick check on our end to ensure everything is accurate before approving your submission.
### Game / Studio Name
You can use a temporary name, or simply describe the genre of your project — for example: "1st-person roguelite shooter". Something is better than nothing!
Submit "N/A" or "Solo Developer" — whichever best describes your situation.
Unfortunately, your submission won't be approved. The Indie subscription is specifically for active game development projects. Video projects, "for hire" dev work, and training simulations are not eligible.
## Can I replace collaborators on Diversion without upgrading my plan?
Yes, as long as the total number of collaborators stays within your plan's limits, there's no need to upgrade. Simply remove the old collaborators and add the new ones to maintain access under your current plan.
# CI/CD
Source: https://docs.diversion.dev/ci-cd
Configure your CI/CD platform to use diversion
## Generate an API Token
Click on your avatar and select *Integrations*.
A new window will open. Click the *Generate a new API token* button.
Provide your login credentials, if prompted.
You'll be redirected to your new API Token.
Use the *Copy* icon to copy the token and store it in a secure place.
This is the only time you'll see the token here and there will be no way to retrieve it later.
If you lose it, you will have to revoke all your API tokens and regenerate new ones.
## Set up your CI/CD platform
Store it as an environment variable named `USER_POOL_CLIENT_ID` with the value `j084768v4hd6j1pf8df4h4c47`.
It will be read and used by the `dv` client in the workflow.
Here are some relevant docs for storing environment variables in popular CI/CD platforms:
* [Jenkins ](https://www.jenkins.io/doc/pipeline/tour/environment/)
* [CircleCI ](https://circleci.com/docs/set-environment-variable/#set-an-environment-variable-in-a-project)
* [TravisCI ](https://docs.travis-ci.com/user/environment-variables/)
* [TeamCity ](https://www.jetbrains.com/help/teamcity/typed-parameters.html#How+to+Create+a+New+Parameter)
* [Bitrise ](https://devcenter.bitrise.io/en/builds/environment-variables.html)
Don't store the API Token as a plain environment variable! If your CI/CD platform provides a secure
secret storage, use it.
Here are some relevant docs for storing secrets in popular CI/CD platforms:
* [Jenkins ](https://www.jenkins.io/doc/developer/security/secrets/#storing-secrets-on-disk)
* [CircleCI ](https://circleci.com/docs/security-recommendations/)
* [TravisCI ](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-settings)
* [TeamCity ](https://www.jetbrains.com/help/teamcity/hashicorp-vault.html)
* [Bitrise ](https://devcenter.bitrise.io/en/builds/secrets.html)
If your platform doesn't support secure secrets handling, you can use external secret handling tools:
* [Hashicorp Vault ](https://www.vaultproject.io/) (has a plugin for TeamCity)
* [Akeyless ](https://docs.akeyless.io/docs/akeyless-overview) (has a plugin for TeamCity)
* [Azure Key Vault ](https://azure.microsoft.com/en-us/products/key-vault) (has a plugin for TeamCity)
* [Google Secret Manager ](https://cloud.google.com/security/products/secret-manager)
* [AWS Secrets Manager ](https://aws.amazon.com/secrets-manager/)
## Create a build step in your CI/CD workflow
### Install the Diversion client, authenticate it and clone your repo
In your CI/CD step editor or `yml` file, create a new *Shell* build step with the following content:
```bash Mac/Linux theme={null}
# Download Diversion client
curl -sL https://get.diversion.dev/unix | bash ; export PATH="$HOME/.diversion/bin:$PATH"
# Start the Diversion agent in the background and wait for it to start
dv --agent --bkg
sleep 2
# Authenticate Diversion
dv authenticate $API_TOKEN
# Clone your repository and wait for sync to complete
dv clone -new-workspace my-repository
cd my-repository
dv status
```
```powershell Windows theme={null}
# Download Diversion client
. ([Scriptblock]::Create((([System.Text.Encoding]::ASCII).getString((Invoke-WebRequest -Uri "https://get.diversion.dev/win-ci").Content))))
# Start the Diversion agent in the background and wait for it to start
dv --agent --bkg
Start-Sleep -Seconds 2
# Authenticate Diversion
dv authenticate $API_TOKEN
# Clone your repository and wait for sync to complete
dv clone -new-workspace my-repository
cd my-repository
dv status
```
Replace `$API_TOKEN` with the appropriate way to reference your secret from the secure storage.
Consult your platform's docs and the secure storage docs.Replace `my-repository` with the name of your repository.`dv status` will block until all the files are downloaded. This is important before starting to work.
It will also output the workspace ID if you want to reuse it for the next runs or view it in the web app.`-new-workspace` will create a new workspace for each run of the CI/CD workflow. Passing a workspace argument here
is important, or else the clone command will prompt for user input and block. See `dv help clone` for details.
## Add the rest of your CI/CD workflow
That's it. You're all set to use your Diversion repo in your CI/CD workflow. You can also use any CLI commands you would
use with `dv` when running locally.
## A Jenkins example
Be sure to replace the placeholders with your actual values. Also note that this syntax is for a Windows node, so you may need to adjust it for your specific setup.
```groovy theme={null}
pipeline
{
agent
{
any
}
environment
{
USER_POOL_CLIENT_ID = "j084768v4hd6j1pf8df4h4c47"
DV_WORKSPACE = "" //Found in Diversion using 'dv workspace' command
DV_REPO = "" //Your repository name
}
stages
{
stage('Sync Repository')
{
steps
{
script
{
// Checking if Diversion CLI is installed and installing from API if not
if (!fileExists("${USERPROFILE}\\.diversion\\bin\\dv.exe"))
{
echo "Diversion not installed at ${USERPROFILE}\\.diversion\\bin\\dv.exe, installing..."
powershell 'iwr https://get.diversion.dev/win-ci | iex'
}
//Authenticating Diversion CLI
withCredentials([string(credentialsId: '', variable: 'API_TOKEN')]) //Insert your credential ID found in Jenkins Credentials
{
echo "Diversion CLI installed, authenticating..."
bat "dv authenticate %API_TOKEN%"
}
//Cloning repository if it is not already cloned
if (!fileExists("${WORKSPACE}\\${DV_REPO}\\.diversion"))
{
echo "Diversion authenticated, empty folder found, cloning repository..."
bat "dv clone ${DV_REPO} -workspace ${DV_WORKSPACE}"
}
//Pulling latest changes if repository is already cloned
else
{
echo "Diversion repository already cloned, pulling latest changes..."
bat "cd ${WORKSPACE}\\${DV_REPO} && dv update"
}
//Displaying status of repository until tasks complete (so we do not start more tasks until it is done)
bat "cd ${WORKSPACE}\\${DV_REPO} && dv status"
}
}
}
}
}
```
# Overview
Source: https://docs.diversion.dev/cmd-ref/about-cmd
Learn how Diversion's command-line interface (CMD) works and simplify your version control workflow.
This section is the reference for Diversion's CLI commands. For in-CLI help, check the [help command](/cmd-ref/help).
To run Diversion on your computer, follow our [Getting Started Guide](../quickstart).
You can type the commands directly into your terminal or shell; append `dv` followed by the command, parameter, and flags.
```bash theme={null}
dv status
```
We recommend using the interactive CLI to get autocompletion and avoid typing `dv` every time. To start the interactive CLI, you just need to type `dv`.
This will open the interactive CLI; from now on, you just need to enter the commands followed by parameters and flags.
```bash theme={null}
clone
```
If you have questions or feedback about this reference, please contact us at our [Discord Server](https://discord.com/invite/HDAGJvgkuT).
# annotate
Source: https://docs.diversion.dev/cmd-ref/annotate
Show line-by-line commit attribution for a file
The `annotate` command shows who last modified each line of a file, along with the commit ID and date. `dv blame` is an alias for this command.
```bash theme={null}
dv annotate [-L ]
```
`` is the file to show annotation information for.
`[-L ]` limits the output to a specific line range. For example, `-L 10,20` shows only lines 10 through 20.
For each line, the output includes:
* **Commit ID** - the commit that last changed the line
* **Author** - who made the change
* **Date** - when the change was made
* **Line number and content** - the current line text
For example, to see who last modified each line in a file:
```bash theme={null}
dv annotate src/main.py
```
To see annotation for a specific range of lines:
```bash theme={null}
dv annotate src/main.py -L 10,20
```
# branch
Source: https://docs.diversion.dev/cmd-ref/branch
Manage branches in the current repo
The branch command allows you to manipulate branches: creating, deleting, and renaming.
## Create a branch
To create a new branch, run:
```bash theme={null}
dv branch -c [-no-checkout]
```
A new branch `branch-name` will be created. If the flag `-no-checkout` is *not* passed, the new branch will be
checked out.
The branch\_name has to be a unique identifier, not named after any other existing branch.
Uncommitted changes will be transferred to the newly created branch.
## Delete a branch
To delete a branch, run:
```bash theme={null}
dv branch -d
```
For convenient autocompletion of the branch name, run the CLI in interactive mode.
This command deletes the branch with the given id as parameter, the ID in this case is the branch’s name.
The `–f` flag is optional and suppresses the confirmation dialog for deleting the branch.
## Rename a branch
```bash theme={null}
dv branch -r
```
The new name parameter has to be a unique identifier, not previously used for any other branch.
# branch-name
Source: https://docs.diversion.dev/cmd-ref/branch-name
Show the current branch name
The `branch-name` command prints the name of the currently checked-out branch.
```bash theme={null}
dv branch-name
```
This is useful for scripting and CI/CD pipelines where you need to retrieve the current branch name programmatically.
# cd
Source: https://docs.diversion.dev/cmd-ref/cd
Change current working directory for an interactive CLI session
## Change working directory
Similarly to your OS' terminal, `cd` allows you to switch the working directory for the Diversion CLI.
```bash theme={null}
dv cd
```
The `` parameter is the path you want to move to.
For example, if you want to move to your Documents directory, you would type:
```bash theme={null}
dv cd /Users/Sloth/Documents/
```
# checkout
Source: https://docs.diversion.dev/cmd-ref/checkout
Switch branches and manage versions efficiently with Diversion's checkout command reference.
Checkout a branch, commit, or tag to your current workspace.
```bash theme={null}
dv checkout [--take-changes] [--shelve-changes] [--discard-changes] [--apply-shelf] [--ignore-shelf]
```
`` is the only mandatory parameter and the options are:
``, or `` if you want to checkout a branch.
`` or ``, if you're checking either of them.
When checking out, there might be some local pending changes or incoming shelved changes. You can specify what to do in each case:
`[--take-changes]` If your worskpace contains any changes, take them with you to the checked out target.
`[--shelve-changes]` If your workspace contains any changes, shelve them for later use.
`[--discard-changes]` Discard any changes in the workspace.
`[--apply-shelf]` If the branch to be checked out contains any previously shelved changes, un-shelve them after check out.
`[--ignore-shelf]` If the branch to be checked out contains any previously shelved changes, ignore them and don't prompt to apply them.
# cherry-pick
Source: https://docs.diversion.dev/cmd-ref/cherry-pick
Apply changes from a specific commit to your current workspace
The `cherry-pick` command allows you to apply the changes from a specific commit into your current workspace without merging the entire branch.
```bash theme={null}
dv cherry-pick
```
The `` parameter is the ID of the commit to cherry-pick.
This is useful when you want to apply specific changes from another branch without merging everything.
An example of cherry-picking a commit:
```bash theme={null}
dv cherry-pick abc123def456
```
The changes from commit `abc123def456` will be applied to your current workspace. You'll need to commit these changes to save them to your branch.
If there are conflicts between the cherry-picked commit and your current workspace, you'll need to resolve them manually.
# clean
Source: https://docs.diversion.dev/cmd-ref/clean
Remove ignored and untracked files from the workspace
The `clean` command removes ignored and untracked files from your workspace, similar to `git clean`.
```bash theme={null}
dv clean [-f]
```
The `-f` flag forces the removal of files without confirmation.
This command is useful for removing build artifacts, temporary files, and other untracked content that you don't want to keep.
This command permanently deletes files. Make sure you don't have any important untracked files before running it.
An example of cleaning the workspace:
```bash theme={null}
dv clean -f
```
This will remove all ignored and untracked files without asking for confirmation.
Files listed in your `.dvignore` file are considered ignored files and will be removed by this command.
# clone
Source: https://docs.diversion.dev/cmd-ref/clone
Clone a repository into your local drive
```bash theme={null}
dv clone [path] [--workspace ] [--new-workspace] [--ref ]
```
If no path is provided, the cloned repository will be cloned under the current directory in a new folder with the same name as the repository.
The `` has to be the id that starts with ws., not the name.
`[--workspace ]` specifies an existing workspace to use after cloning.
`[--new-workspace]` forces creating a new workspace rather than prompting.
`[--ref ]` checks out a specific branch name, branch ID, commit ID, or tag ID after cloning. If unspecified, the default branch is checked out.
# commit
Source: https://docs.diversion.dev/cmd-ref/commit
Add changes to your active branch
In Diversion, you call the commit command to add the changes in your active workspace to the active branch.
```bash theme={null}
dv commit [files...] [-a] -m [--no-verify]
```
You can specify which files to commit individually or use the `[-a]` parameter to commit all the changes.
A commit message is required preceded by the `-m` flag. The commit message needs to be "surrounded by quotes."
`[--no-verify]` skips pre-commit hooks.
An example on how to add all the files to a commit would be:
```bash theme={null}
dv commit -a -m "Implemented running animations."
```
Once committed, the changes will be replicated across all users on the same branch.
Use the `--no-verify` flag to skip [pre-commit hooks](/advanced/pre-commit-hooks) for a single commit:
```bash theme={null}
dv commit -a -m "quick fix" --no-verify
```
# diff
Source: https://docs.diversion.dev/cmd-ref/diff
Compare changes between branches or commits with Diversion's diff command for clear version insights.
The `diff` command allows you to compare changes between your current workspace, branches, commits, or tags.
```bash theme={null}
dv diff [paths...] [--base ] [--compare ] [--name-status] [--color ]
```
`[paths...]` is a file or directory to compare. If omitted, Diversion compares the entire repository.
`[--base ]` sets the base reference to compare from (branch name, commit ID, or tag). Defaults to the workspace's base commit.
`[--compare ]` sets the reference to compare to (branch name, commit ID, or tag). Defaults to the current workspace.
`[--name-status]` shows only names and status of changed files (A=added, M=modified, D=deleted, R=renamed).
`[--color ]` controls color output. Defaults to `auto`.
For example, to see what changed between two branches:
```bash theme={null}
dv diff --base main --compare feature-branch
```
To see just a summary of changed files:
```bash theme={null}
dv diff --name-status
```
# feedback
Source: https://docs.diversion.dev/cmd-ref/feedback
Provide your feedback to Diversion devs
We love and appreciate your feedback; this command will open up a browser window with a form you can use to send your comments.
```bash theme={null}
dv feedback
```
Additionally, you can visit our [Discord Server](https://discord.com/invite/HDAGJvgkuT) for support.
# help
Source: https://docs.diversion.dev/cmd-ref/help
Get more information about Diversion's commands
To get in-CLI help about working with Diversion CLI, you can use the help command, followed by any other command in this guide.
```bash theme={null}
dv help [command]
```
For example, if you want to get more information about how the `clone` command works, you would input the following:
```bash theme={null}
dv help clone
```
# import
Source: https://docs.diversion.dev/cmd-ref/import
Bring your Git repository to Diversion
This command allows you to import your Git project (currently, only GitHub over HTTPS URL is supported).
```bash theme={null}
dv import [repo_name] [--with-sync] [--with-history] [--git_branch ]
```
The `` is the URL from your GitHub repository. Optionally, you can provide a `[repo_name]` if you want Diversion to name it differently than the repository you are importing.
You can tell Diversion to keep your repository synced with the Git repository (changes in either will be propagated to the other). Use the `[--with-sync]` parameter if you need this.
You can tell Diversion to import either the repository's head (the latest commit) or the entire repository's history. Specify this using the `[--with-history]` parameter.
You can also indicate which branch you want to import or all the branches. By default, Diversion will import the default branch.
# init
Source: https://docs.diversion.dev/cmd-ref/init
Initialize a repository
The init command initializes a Diversion repository from your local drive. Diversion will create a cloud project with the provided parameters.
```bash theme={null}
dv init [--f]
```
The path is the location where you want Diversion to initialize your project. If you want to initialize in the current directory, provide `.` as the parameter.
You can define the repository's name (which will appear in the web dashboard). If no name is specified, Diversion will take the last path component of the directory.
# invite
Source: https://docs.diversion.dev/cmd-ref/invite
Invite collaborators
To add contributors to your repository, you use the invite command:
```bash theme={null}
dv invite --access
```
`--access ` defines the level of access you want to provide to this collaborator; the options for `` are:
* `READ`
* `WRITE`
* `ADMIN`
* `OWNER`
The collaborators need a Diversion account before they can access the repository.
## accept
To accept a pending repository invitation:
```bash theme={null}
dv invite accept
```
# log
Source: https://docs.diversion.dev/cmd-ref/log
Get the latest commits
You use the log command to get the list of commits in your repository.
```bash theme={null}
dv log [path] [-n ] [--oneline] [--since ] [--until ] [--date ]
```
`[path]` filters commits to only those affecting a specific file or directory.
`[-n ]` limits the number of commits shown (default 20, max 1000).
`[--oneline]` shows each commit on a single line.
`[--since ]` shows commits after a date (ISO format or relative like `1 week ago`).
`[--until ]` shows commits before a date.
`[--date ]` sets the output date format. Use `iso` for ISO 8601 UTC.
An example of fetching the last ten commits:
```bash theme={null}
dv log -n 10
```
To see commits affecting a specific file:
```bash theme={null}
dv log path/to/file.uasset
```
To see recent commits in compact format:
```bash theme={null}
dv log --oneline --since "2 weeks ago"
```
# login
Source: https://docs.diversion.dev/cmd-ref/login
Login to your Diversion account
Logs you into your Diversion account via the command line. It will open a browser window for you to enter your credentials. After a successful login, you can return to the command line and start working.
```bash theme={null}
dv login
```
# logout
Source: https://docs.diversion.dev/cmd-ref/logout
Log out securely from Diversion CLI and manage session access with the logout command.
To logout from your current signed-in account, you simply use the logout command:
```bash theme={null}
dv logout
```
# ls
Source: https://docs.diversion.dev/cmd-ref/ls
List repository files, branches, and workspaces using the Diversion ls command for quick project overview.
```bash theme={null}
dv ls