oh-my-space 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +53 -36
  2. package/dist/oms.js +419 -436
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,15 +1,26 @@
1
1
  # oh-my-space
2
2
 
3
- `oh-my-space` provides the `oms` CLI for managing external source repositories declared in `oms.yaml`. Each registered repo lives as a bare clone under `oms/<alias>/.bare/` and the baseline branch (and any additional ones you ask for) checks out as a Git worktree at `oms/<alias>/<branch>/`.
3
+ `oh-my-space` provides the `oms` CLI for managing external source repositories declared in `oms.yaml`. Each registered repo is checked out as a **git submodule** at `oms/<alias>/`, so its pinned commit, branch, and history are tracked natively by your project — and `oms` wraps the submodule foot-guns (detached HEAD, remote-first branch creation, easy-to-miss pointer moves) behind a small, friendly command set.
4
4
 
5
5
  Package name: `oh-my-space`
6
6
 
7
7
  Command name: `oms`
8
8
 
9
+ ## Why submodules + a wrapper
10
+
11
+ Git submodules give you three things for free: a **reproducible pin** (the parent records each source's exact commit), **visibility** (`git status` shows when a pointer moved), and **history** (the pointer travels with your commits). What they make awkward is day-to-day branch work. `oms` keeps the native benefits and removes the friction:
12
+
13
+ - **Create a new branch locally, with no remote precondition.** `oms checkout <alias> <branch>` makes the branch right away even if it does not exist on the remote yet. The remote branch is created lazily on your first `oms push`.
14
+ - **Always on a branch, never detached.** `oms sync` attaches the baseline branch at the pinned commit instead of leaving a detached HEAD.
15
+ - **Pointer moves stay visible.** `oms pull` / `oms push` stage the updated gitlink in the parent so you can see and commit it; `oms status` surfaces drift.
16
+
17
+ > Sharing a pin with your team still requires pushing the commit — that is inherent to any pinning model. `oms` removes the *local* friction; it cannot make an unpushed commit reproducible for others.
18
+
9
19
  ## Requirements
10
20
 
11
21
  - [Node.js](https://nodejs.org) `>=20.19.0` for running `oms`; development uses the version in `.nvmrc` (`24`)
12
- - git `>=2.40` (worktree `--track -B` flow)
22
+ - git `>=2.40` (`git switch` + submodule commands)
23
+ - The workspace must be a git repository (`git init`), since sources are submodules of it.
13
24
 
14
25
  For local development:
15
26
 
@@ -32,9 +43,10 @@ bun install -g oh-my-space
32
43
 
33
44
  ## Quick start
34
45
 
35
- Create an `oms.yaml` in your project root:
46
+ Run `oms init` to scaffold a starter `oms.yaml`, or create one by hand in your project root:
36
47
 
37
48
  ```yaml
49
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/divlook/oh-my-space/main/oms.schema.json
38
50
  repos:
39
51
  - alias: api
40
52
  url: git@github.com:example/api.git
@@ -43,57 +55,61 @@ repos:
43
55
  url: git@github.com:example/web.git
44
56
  ```
45
57
 
46
- Sync and explore:
58
+ Sync and work:
47
59
 
48
60
  ```bash
49
- oms doctor # validate oms.yaml + bare/worktree state
50
- oms sync --list # list registered source repos
51
- oms sync <alias>... # bare-clone + create the baseline worktree
52
- oms sync --all # sync every registered source repo
53
- oms sync # interactive multi-select
54
- oms worktree add <alias> <branch> # add another worktree alongside the baseline
55
- oms worktree list [alias] # show every worktree
56
- oms worktree remove <alias> <br> # remove a single worktree
57
- oms unsync <alias>... # remove ALL worktrees + the bare clone
61
+ oms init # scaffold a starter oms.yaml
62
+ oms doctor # validate oms.yaml + submodule state
63
+ oms sync --list # list registered source repos
64
+ oms sync <alias>... # add/initialize submodules on their baseline branch
65
+ oms sync --all # sync every registered source repo
66
+ oms status # branch / pointer / dirty / ahead-behind per submodule
67
+ oms checkout <alias> <branch> # switch (or create a brand-new local branch)
68
+ oms push <alias>... # push the branch (lazy remote) + stage the pointer
69
+ oms unsync <alias>... # deinitialize and remove a submodule
58
70
  ```
59
71
 
60
- `oms sync` adds `oms/` to your workspace `.gitignore` on first run; the bare clone and worktrees stay out of your project history.
72
+ A typical new-branch flow:
73
+
74
+ ```bash
75
+ oms checkout api feature/login # local branch, no remote needed
76
+ # ... edit, commit inside oms/api ...
77
+ oms push api # creates origin/feature/login and stages the pointer
78
+ git add oms/api && git commit # record the pointer in your project history
79
+ ```
61
80
 
62
81
  ## Layout
63
82
 
64
- For an alias `api` with the baseline branch `main` and an extra `feature/foo` worktree:
83
+ For an alias `api` checked out on `main`:
65
84
 
66
85
  ```
86
+ .gitmodules # registers oms/api -> url, branch
67
87
  oms/
68
- └── api/
69
- ├── .bare/ # git clone --bare result
70
- ├── .git # 'gitdir: ./.bare' placeholder
71
- ├── main/ # worktree for main (upstream: origin/main)
72
- └── feature/
73
- └── foo/ # worktree for feature/foo
88
+ └── api/ # git submodule (a normal working tree, on a branch)
74
89
  ```
75
90
 
76
- Slash-containing branch names are kept nested as directories.
91
+ `.gitmodules` and the `oms/<alias>` gitlink are part of your project history. Submodules must **not** be gitignored; `oms sync` removes a stale `oms/` entry from `.gitignore` if a previous version added one.
77
92
 
78
93
  ## Managing source repositories
79
94
 
80
- `oms.yaml` declares each source repo with `alias`, `url`, and optional `branch` (the baseline). Additional worktrees are created on demand with `oms worktree add` and are *not* persisted in `oms.yaml` — they're treated as per-machine working space.
95
+ `oms.yaml` declares each source repo with `alias`, `url`, and optional `branch` (the baseline).
81
96
 
82
97
  | Command | Runs in | Does | Notes |
83
98
  | --- | --- | --- | --- |
84
- | `oms doctor` | project root or child path | Checks `oms.yaml`, git availability, `.gitignore`, and each alias's bare clone + `remote.origin.fetch`. | Returns exit 2 if any warning is raised. |
85
- | `oms sync <alias>` / `--all` | workspace root | Bare-clones missing repos, fetches origin, creates the baseline worktree. | Adds `oms/` to `.gitignore` if absent. |
86
- | `oms unsync <alias>` / `--all` | workspace root | Removes every worktree, the bare clone, and the `.git` placeholder for the alias. | Keeps the `oms.yaml` entry. Use `--force` to discard uncommitted changes. |
87
- | `oms fetch ...` | workspace root | `git fetch origin --prune` on each bare clone. | Worktrees are not touched. |
88
- | `oms pull ...` | workspace root | `git pull --ff-only` on the baseline worktree of each selected alias. | Requires the worktree to be on its branch with upstream set (the default after `oms sync`). |
89
- | `oms push <alias>...` | workspace root | `git push` on the baseline worktree of each explicitly listed alias. | No `--all`, no force, no automatic upstream setup. |
90
- | `oms worktree add <alias> <branch>` | workspace root | `git worktree add --track -B <branch> <branch> origin/<branch>` inside the alias. | Slash branches become nested directories. |
91
- | `oms worktree list [alias]` | anywhere under root | Lists every worktree for the alias (or all aliases). | |
92
- | `oms worktree remove <alias> <branch>` | workspace root | `git worktree remove <branch>` plus parent-directory cleanup for slash branches. | `--force` discards uncommitted changes. |
99
+ | `oms init` | current directory | Writes a starter `oms.yaml`. | Refuses if `oms.yaml` exists; use `--force`. Does not gitignore `oms/`. |
100
+ | `oms doctor` | project root or child path | Checks `oms.yaml`, git availability, that the workspace is a git repo, and each alias's submodule state. | Returns exit 2 if any warning is raised. |
101
+ | `oms sync <alias>` / `--all` | workspace root | Registers missing repos with `git submodule add`, initializes registered-but-uninitialized ones, fetches, and attaches the baseline branch. | Reproduces the recorded pointer on a fresh clone. |
102
+ | `oms status [alias...]` / `--all` | anywhere under root | Prints branch, pointer state (`ok`/`moved`/`uninit`), dirtiness, and ahead/behind for each submodule. | `moved` means the working commit differs from the recorded pointer — stage/commit it. |
103
+ | `oms checkout <alias> <branch>` | workspace root | `git switch` to the branch; creates it locally if it exists nowhere yet (no remote required). | `--from <ref>` sets the start point for a new branch. |
104
+ | `oms fetch ...` | workspace root | `git fetch origin --prune` in each submodule. | |
105
+ | `oms pull ...` | workspace root | `git pull --ff-only` on each submodule's current branch, then stages the moved pointer. | Requires the submodule to be on a branch with upstream. |
106
+ | `oms push <alias>...` | workspace root | `git push -u origin <branch>` (creating the remote branch on first push), then stages the moved pointer. | `--commit` also commits the pointer update in the parent. |
107
+ | `oms unsync <alias>` / `--all` | workspace root | `git submodule deinit` + `git rm` for the alias; drops an empty `.gitmodules`. | Keeps the `oms.yaml` entry. Use `--force` to discard uncommitted changes. |
93
108
 
94
109
  ## `oms.yaml` format
95
110
 
96
111
  ```yaml
112
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/divlook/oh-my-space/main/oms.schema.json
97
113
  repos:
98
114
  - alias: service-a
99
115
  url: git@github.com:example/service-a.git
@@ -107,16 +123,17 @@ Rules:
107
123
  - `repos` must be a non-empty array.
108
124
  - `alias` must be unique and match `/^[a-z0-9][a-z0-9-]*$/`.
109
125
  - `url` is required.
110
- - `branch` is optional; when omitted the bare clone's default branch is used as the baseline worktree.
126
+ - `branch` is optional; when omitted the remote's default branch is used as the baseline.
111
127
 
112
128
  JSON schema: [`oms.schema.json`](./oms.schema.json) (also reachable at `https://raw.githubusercontent.com/divlook/oh-my-space/main/oms.schema.json` for YAML LSPs).
113
129
 
114
130
  ## Migrating between versions
115
131
 
116
- 자세한 마이그레이션 절차는 [`docs/migrations/`](./docs/migrations/) 에 버전별로 정리되어 있습니다.
132
+ Detailed migration steps are organized per version under [`docs/migrations/`](./docs/migrations/).
117
133
 
118
- - [0.3.x → 0.4.0](./docs/migrations/0.3.x-to-0.4.0.md) — `sources.yaml`/`sources/` 가 `oms.yaml`/`oms/` 로 rename
119
- - [0.2.x → 0.3.0](./docs/migrations/0.2.x-to-0.3.0.md) — submodule 에서 bare clone + worktree 로 데이터 모델 전환
134
+ - [0.5.x → 0.6.0](./docs/migrations/0.5.x-to-0.6.0.md) — switches the data model from bare clone + worktrees back to git submodules
135
+ - [0.3.x → 0.4.0](./docs/migrations/0.3.x-to-0.4.0.md) — renames `sources.yaml`/`sources/` to `oms.yaml`/`oms/`
136
+ - [0.2.x → 0.3.0](./docs/migrations/0.2.x-to-0.3.0.md) — (historical) switched submodules to bare clone + worktrees
120
137
 
121
138
  ## License
122
139