oh-my-space 0.5.0 → 0.7.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.
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,67 +43,72 @@ bun install -g oh-my-space
32
43
 
33
44
  ## Quick start
34
45
 
35
- Run `oms init` to scaffold a starter `oms.yaml` (also adds `oms/` to `.gitignore`), or create one by hand 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
38
49
  # yaml-language-server: $schema=https://raw.githubusercontent.com/divlook/oh-my-space/main/oms.schema.json
39
50
  repos:
40
51
  - alias: api
41
- url: git@github.com:example/api.git
52
+ remotes:
53
+ origin: git@github.com:example/api.git
42
54
  branch: main
43
55
  - alias: web
44
- url: git@github.com:example/web.git
56
+ remotes:
57
+ origin: git@github.com:example/web.git
58
+ upstream: git@github.com:upstream/web.git
45
59
  ```
46
60
 
47
- Sync and explore:
61
+ Sync and work:
48
62
 
49
63
  ```bash
50
- oms init # scaffold a starter oms.yaml
51
- oms doctor # validate oms.yaml + bare/worktree state
52
- oms sync --list # list registered source repos
53
- oms sync <alias>... # bare-clone + create the baseline worktree
54
- oms sync --all # sync every registered source repo
55
- oms sync # interactive multi-select
56
- oms worktree add <alias> <branch> # add another worktree alongside the baseline
57
- oms worktree list [alias] # show every worktree
58
- oms worktree remove <alias> <br> # remove a single worktree
59
- oms unsync <alias>... # remove ALL worktrees + the bare clone
64
+ oms init # scaffold a starter oms.yaml
65
+ oms doctor # validate oms.yaml + submodule state
66
+ oms sync --list # list registered source repos
67
+ oms sync <alias>... # add/initialize submodules on their baseline branch
68
+ oms sync --all # sync every registered source repo
69
+ oms status # branch / pointer / dirty / ahead-behind per submodule
70
+ oms checkout <alias> <branch> # switch (or create a brand-new local branch)
71
+ oms push <alias>... # push the branch (lazy remote) + stage the pointer
72
+ oms push <alias> --remote upstream # target a specific remote (repeatable; defaults to origin)
73
+ oms unsync <alias>... # deinitialize and remove a submodule
60
74
  ```
61
75
 
62
- `oms sync` adds `oms/` to your workspace `.gitignore` on first run; the bare clone and worktrees stay out of your project history.
76
+ A typical new-branch flow:
77
+
78
+ ```bash
79
+ oms checkout api feature/login # local branch, no remote needed
80
+ # ... edit, commit inside oms/api ...
81
+ oms push api # creates origin/feature/login and stages the pointer
82
+ git add oms/api && git commit # record the pointer in your project history
83
+ ```
63
84
 
64
85
  ## Layout
65
86
 
66
- For an alias `api` with the baseline branch `main` and an extra `feature/foo` worktree:
87
+ For an alias `api` checked out on `main`:
67
88
 
68
89
  ```
90
+ .gitmodules # registers oms/api -> origin url, branch
69
91
  oms/
70
- └── api/
71
- ├── .bare/ # git clone --bare result
72
- ├── .git # 'gitdir: ./.bare' placeholder
73
- ├── main/ # worktree for main (upstream: origin/main)
74
- └── feature/
75
- └── foo/ # worktree for feature/foo
92
+ └── api/ # git submodule (a normal working tree, on a branch)
76
93
  ```
77
94
 
78
- Slash-containing branch names are kept nested as directories.
95
+ `.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.
79
96
 
80
97
  ## Managing source repositories
81
98
 
82
- `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.
99
+ `oms.yaml` declares each source repo with `alias`, a `remotes` mapping (which must include `origin`), and optional `branch` (the baseline).
83
100
 
84
101
  | Command | Runs in | Does | Notes |
85
102
  | --- | --- | --- | --- |
86
- | `oms init` | current directory | Writes a starter `oms.yaml` and adds `oms/` to `.gitignore`. | Refuses if `oms.yaml` exists; use `--force` to overwrite. |
87
- | `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. |
88
- | `oms sync <alias>` / `--all` | workspace root | Bare-clones missing repos, fetches origin, creates the baseline worktree. | Adds `oms/` to `.gitignore` if absent. |
89
- | `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. |
90
- | `oms fetch ...` | workspace root | `git fetch origin --prune` on each bare clone. | Worktrees are not touched. |
91
- | `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`). |
92
- | `oms push <alias>...` | workspace root | `git push` on the baseline worktree of each explicitly listed alias. | No `--all`, no force, no automatic upstream setup. |
93
- | `oms worktree add <alias> <branch>` | workspace root | `git worktree add --track -B <branch> <branch> origin/<branch>` inside the alias. | Slash branches become nested directories. |
94
- | `oms worktree list [alias]` | anywhere under root | Lists every worktree for the alias (or all aliases). | |
95
- | `oms worktree remove <alias> <branch>` | workspace root | `git worktree remove <branch>` plus parent-directory cleanup for slash branches. | `--force` discards uncommitted changes. |
103
+ | `oms init` | current directory | Writes a starter `oms.yaml`. | Refuses if `oms.yaml` exists; use `--force`. Does not gitignore `oms/`. |
104
+ | `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. |
105
+ | `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. |
106
+ | `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. |
107
+ | `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. |
108
+ | `oms fetch ...` | workspace root | `git fetch <remote> --prune` in each submodule. | `--remote <name>` (repeatable) picks the remote(s); omit to choose interactively, defaults to `origin`. |
109
+ | `oms pull ...` | workspace root | `git pull --ff-only <remote>` on each submodule's current branch, then stages the moved pointer. | Requires the submodule to be on a branch. `--remote <name>` selects a single remote (defaults to `origin`). |
110
+ | `oms push <alias>...` | workspace root | `git push <remote> <branch>` (creating the remote branch on first push), then stages the moved pointer. | `--remote <name>` (repeatable) picks the remote(s), defaults to `origin`; upstream is set only for `origin`. `--commit` also commits the pointer update in the parent. |
111
+ | `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. |
96
112
 
97
113
  ## `oms.yaml` format
98
114
 
@@ -100,27 +116,31 @@ Slash-containing branch names are kept nested as directories.
100
116
  # yaml-language-server: $schema=https://raw.githubusercontent.com/divlook/oh-my-space/main/oms.schema.json
101
117
  repos:
102
118
  - alias: service-a
103
- url: git@github.com:example/service-a.git
119
+ remotes:
120
+ origin: git@github.com:example/service-a.git
104
121
  branch: main
105
122
  - alias: docs
106
- url: https://github.com/example/docs.git
123
+ remotes:
124
+ origin: https://github.com/example/docs.git
125
+ upstream: https://github.com/upstream/docs.git
107
126
  ```
108
127
 
109
128
  Rules:
110
129
 
111
130
  - `repos` must be a non-empty array.
112
131
  - `alias` must be unique and match `/^[a-z0-9][a-z0-9-]*$/`.
113
- - `url` is required.
114
- - `branch` is optional; when omitted the bare clone's default branch is used as the baseline worktree.
132
+ - `remotes` is required and must include an `origin` entry; each value is a clonable git URL. `origin` becomes the submodule's primary remote, and additional remotes are configured on `oms sync`.
133
+ - `branch` is optional; when omitted the remote's default branch is used as the baseline.
115
134
 
116
135
  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).
117
136
 
118
137
  ## Migrating between versions
119
138
 
120
- 자세한 마이그레이션 절차는 [`docs/migrations/`](./docs/migrations/) 에 버전별로 정리되어 있습니다.
139
+ Detailed migration steps are organized per version under [`docs/migrations/`](./docs/migrations/).
121
140
 
122
- - [0.3.x → 0.4.0](./docs/migrations/0.3.x-to-0.4.0.md) — `sources.yaml`/`sources/` 가 `oms.yaml`/`oms/` 로 rename
123
- - [0.2.x → 0.3.0](./docs/migrations/0.2.x-to-0.3.0.md) — submodule 에서 bare clone + worktree 로 데이터 모델 전환
141
+ - [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
142
+ - [0.3.x → 0.4.0](./docs/migrations/0.3.x-to-0.4.0.md) — renames `sources.yaml`/`sources/` to `oms.yaml`/`oms/`
143
+ - [0.2.x → 0.3.0](./docs/migrations/0.2.x-to-0.3.0.md) — (historical) switched submodules to bare clone + worktrees
124
144
 
125
145
  ## License
126
146
 
@@ -0,0 +1 @@
1
+ {"commit":"23dd80c9eef2a1ba62b193a9497f564dbe116739"}