gitmux 0.1.0__tar.gz
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.
- gitmux-0.1.0/.github/workflows/publish.yml +27 -0
- gitmux-0.1.0/.gitignore +8 -0
- gitmux-0.1.0/DESIGN.md +96 -0
- gitmux-0.1.0/LICENSE +21 -0
- gitmux-0.1.0/PKG-INFO +221 -0
- gitmux-0.1.0/README.md +190 -0
- gitmux-0.1.0/pyproject.toml +62 -0
- gitmux-0.1.0/src/gitmux/__init__.py +3 -0
- gitmux-0.1.0/src/gitmux/cli.py +535 -0
- gitmux-0.1.0/src/gitmux/config.py +131 -0
- gitmux-0.1.0/src/gitmux/executor.py +125 -0
- gitmux-0.1.0/src/gitmux/git_ops.py +103 -0
- gitmux-0.1.0/src/gitmux/hooks.py +59 -0
- gitmux-0.1.0/src/gitmux/models.py +63 -0
- gitmux-0.1.0/src/gitmux/output.py +31 -0
- gitmux-0.1.0/tests/__init__.py +0 -0
- gitmux-0.1.0/tests/test_config.py +194 -0
- gitmux-0.1.0/tests/test_executor.py +57 -0
- gitmux-0.1.0/tests/test_git_ops.py +105 -0
- gitmux-0.1.0/tests/test_hooks.py +59 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install build tools
|
|
21
|
+
run: pip install build
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: python -m build
|
|
25
|
+
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
gitmux-0.1.0/.gitignore
ADDED
gitmux-0.1.0/DESIGN.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# gitmux - Design Document
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
gitmux 是一个 Python CLI 工具,通过 YAML 配置文件管理多个 git 仓库,支持批量 git 操作、分组管理、前后置 hook、并行/串行执行模式。
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/gitmux/
|
|
11
|
+
├── cli.py # Typer CLI 入口,子命令定义
|
|
12
|
+
├── config.py # YAML 配置加载/验证/保存
|
|
13
|
+
├── models.py # 数据模型(Repo, Group, Hook, Template)
|
|
14
|
+
├── executor.py # 命令执行引擎(串行/并行)
|
|
15
|
+
├── git_ops.py # Git 操作封装
|
|
16
|
+
├── hooks.py # Hook 执行逻辑
|
|
17
|
+
└── output.py # 输出格式化(Rich 表格、进度条)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration Format
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
workspace: ~/projects
|
|
24
|
+
|
|
25
|
+
templates:
|
|
26
|
+
node-app:
|
|
27
|
+
post_pull:
|
|
28
|
+
- npm install
|
|
29
|
+
pre_push:
|
|
30
|
+
- npm test
|
|
31
|
+
|
|
32
|
+
groups:
|
|
33
|
+
backend:
|
|
34
|
+
repos:
|
|
35
|
+
- name: api-server
|
|
36
|
+
url: git@github.com:user/api-server.git
|
|
37
|
+
template: node-app
|
|
38
|
+
- name: auth-service
|
|
39
|
+
url: git@github.com:user/auth-service.git
|
|
40
|
+
path: ~/custom/path/auth
|
|
41
|
+
hooks:
|
|
42
|
+
post_pull:
|
|
43
|
+
- pip install -r requirements.txt
|
|
44
|
+
branches:
|
|
45
|
+
prod: "auth-plan-*"
|
|
46
|
+
dev: "auth-dev-main"
|
|
47
|
+
frontend:
|
|
48
|
+
repos:
|
|
49
|
+
- name: web-app
|
|
50
|
+
url: git@github.com:user/web-app.git
|
|
51
|
+
template: node-app
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## CLI Commands
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
gitmux init # 初始化配置文件
|
|
58
|
+
gitmux add <url> --group=<group> # 添加仓库
|
|
59
|
+
gitmux remove <name> # 移除仓库
|
|
60
|
+
gitmux list # 列出所有仓库
|
|
61
|
+
gitmux status [--group=<group>] # 状态总览
|
|
62
|
+
gitmux clone [--group=<group>] # 克隆未克隆的仓库
|
|
63
|
+
gitmux fetch [--group=<group>] [--branches] [--parallel]
|
|
64
|
+
gitmux pull [--group=<group>] [--branch=<alias|alias:latest|alias:value>] [--parallel]
|
|
65
|
+
gitmux push [--group=<group>] [--parallel]
|
|
66
|
+
gitmux exec <command> [--group=<group>] [--parallel]
|
|
67
|
+
gitmux group list
|
|
68
|
+
gitmux group create <name>
|
|
69
|
+
gitmux group remove <name>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Execution Flow
|
|
73
|
+
|
|
74
|
+
1. 用户执行命令
|
|
75
|
+
2. 查找配置文件:`--config` 指定 → 当前目录 `.gitmux.yaml` → `~/.gitmux.yaml`
|
|
76
|
+
3. 加载配置,解析目标仓库列表(按 --group 过滤)
|
|
77
|
+
3. 判断串行/并行模式
|
|
78
|
+
4. 对每个仓库执行:pre-hook → git 操作 → post-hook
|
|
79
|
+
5. 输出结果
|
|
80
|
+
|
|
81
|
+
### Hook 错误处理
|
|
82
|
+
- pre-hook 失败 → 中断该仓库的 git 操作
|
|
83
|
+
- post-hook 失败 → 标记仓库失败
|
|
84
|
+
|
|
85
|
+
### 输出模式
|
|
86
|
+
- 串行:实时输出,显示当前仓库名和执行步骤
|
|
87
|
+
- 并行:Rich 进度条,完成后汇总(成功/失败/详情)
|
|
88
|
+
|
|
89
|
+
## Technical Stack
|
|
90
|
+
- CLI: Typer
|
|
91
|
+
- Terminal UI: Rich
|
|
92
|
+
- Config: PyYAML
|
|
93
|
+
- Parallelism: concurrent.futures.ThreadPoolExecutor
|
|
94
|
+
- Git: subprocess
|
|
95
|
+
- Testing: pytest
|
|
96
|
+
- Build: hatchling
|
gitmux-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ryan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
gitmux-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gitmux
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Manage multiple git repositories with ease
|
|
5
|
+
Project-URL: Homepage, https://github.com/ryan/gitmux
|
|
6
|
+
Project-URL: Repository, https://github.com/ryan/gitmux
|
|
7
|
+
Project-URL: Issues, https://github.com/ryan/gitmux/issues
|
|
8
|
+
Author: Ryan
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,devtools,git,multi-repo
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
24
|
+
Requires-Dist: rich>=13.9.4
|
|
25
|
+
Requires-Dist: typer>=0.15.4
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest-mock==3.14.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest==8.3.4; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff==0.11.12; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# gitmux
|
|
33
|
+
|
|
34
|
+
Manage multiple git repositories with ease. Clone, pull, push, and run commands across repos with a single command.
|
|
35
|
+
|
|
36
|
+
## Features
|
|
37
|
+
|
|
38
|
+
- **YAML configuration** — declarative repo management
|
|
39
|
+
- **Group management** — organize repos into groups
|
|
40
|
+
- **Batch git operations** — clone/pull/push across repos
|
|
41
|
+
- **Pre/post hooks** — run commands before/after git operations (e.g., `npm install` after pull)
|
|
42
|
+
- **Template system** — share hook configs across similar repos
|
|
43
|
+
- **Parallel execution** — speed up operations with `--parallel` flag
|
|
44
|
+
- **Status overview** — see all repos' git status at a glance
|
|
45
|
+
- **Arbitrary command execution** — run any shell command across repos
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install gitmux
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Initialize config in current directory
|
|
57
|
+
gitmux init
|
|
58
|
+
|
|
59
|
+
# Add repos (default group if --group omitted)
|
|
60
|
+
gitmux add git@github.com:user/api-server.git --group backend
|
|
61
|
+
gitmux add git@github.com:user/auth-service.git --group backend
|
|
62
|
+
|
|
63
|
+
# Clone all repos
|
|
64
|
+
gitmux clone --all
|
|
65
|
+
|
|
66
|
+
# Pull a single repo
|
|
67
|
+
gitmux pull backend/api-server
|
|
68
|
+
|
|
69
|
+
# Pull entire group (parallel)
|
|
70
|
+
gitmux pull --group backend --parallel
|
|
71
|
+
|
|
72
|
+
# Check status of all repos
|
|
73
|
+
gitmux status
|
|
74
|
+
|
|
75
|
+
# Run command on a specific repo
|
|
76
|
+
gitmux exec "git checkout main" --target backend/api-server
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Configuration
|
|
80
|
+
|
|
81
|
+
Config file lookup order (used for both reading and writing):
|
|
82
|
+
1. `--config / -c` flag (explicit path)
|
|
83
|
+
2. `.gitmux.yaml` in current directory
|
|
84
|
+
3. `~/.gitmux.yaml` (global fallback)
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
workspace: ~/projects
|
|
88
|
+
|
|
89
|
+
templates:
|
|
90
|
+
node-app:
|
|
91
|
+
post_pull:
|
|
92
|
+
- npm install
|
|
93
|
+
pre_push:
|
|
94
|
+
- npm test
|
|
95
|
+
|
|
96
|
+
groups:
|
|
97
|
+
backend:
|
|
98
|
+
repos:
|
|
99
|
+
- name: api-server
|
|
100
|
+
url: git@github.com:user/api-server.git
|
|
101
|
+
template: node-app
|
|
102
|
+
- name: auth-service
|
|
103
|
+
url: git@github.com:user/auth-service.git
|
|
104
|
+
path: ~/custom/path/auth # override default path
|
|
105
|
+
hooks:
|
|
106
|
+
post_pull:
|
|
107
|
+
- pip install -r requirements.txt
|
|
108
|
+
frontend:
|
|
109
|
+
repos:
|
|
110
|
+
- name: web-app
|
|
111
|
+
url: git@github.com:user/web-app.git
|
|
112
|
+
template: node-app
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Path Resolution
|
|
116
|
+
|
|
117
|
+
- Default: `{workspace}/{group}/{repo_name}`
|
|
118
|
+
- Override per-repo with the `path` field
|
|
119
|
+
|
|
120
|
+
### Branch Management
|
|
121
|
+
|
|
122
|
+
Configure named branch aliases per repo:
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
repos:
|
|
126
|
+
- name: map
|
|
127
|
+
url: https://code.example.com/base/map.git
|
|
128
|
+
branches:
|
|
129
|
+
prod: "bInfinite-plan-*" # pattern (contains *)
|
|
130
|
+
dev: "bInfinite-dev-main" # fixed branch name
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Usage:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
gitmux pull map --branch dev # checkout fixed branch → pull
|
|
137
|
+
gitmux pull map --branch prod:latest # fetch → find newest matching branch → checkout → pull
|
|
138
|
+
gitmux pull map --branch prod:260515 # replace * → checkout bInfinite-plan-260515 → pull
|
|
139
|
+
gitmux pull --group base --branch dev # checkout fixed branch for all repos in group
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Rules:
|
|
143
|
+
- `--branch <alias>` — alias must be a fixed branch (no `*`), otherwise error
|
|
144
|
+
- `--branch <alias>:latest` — alias must be a pattern (has `*`), picks newest by commit date
|
|
145
|
+
- `--branch <alias>:<value>` — alias must be a pattern, replaces `*` with `<value>`
|
|
146
|
+
|
|
147
|
+
### Hook System
|
|
148
|
+
|
|
149
|
+
Hooks run shell commands before/after git operations:
|
|
150
|
+
|
|
151
|
+
- `pre_clone`, `post_clone`
|
|
152
|
+
- `pre_pull`, `post_pull`
|
|
153
|
+
- `pre_push`, `post_push`
|
|
154
|
+
|
|
155
|
+
**Error handling:**
|
|
156
|
+
- Pre-hook failure → git operation is skipped
|
|
157
|
+
- Post-hook failure → repo marked as failed
|
|
158
|
+
|
|
159
|
+
**Template merging:** Repo-level hooks override template hooks per hook type.
|
|
160
|
+
|
|
161
|
+
## Commands
|
|
162
|
+
|
|
163
|
+
| Command | Description |
|
|
164
|
+
|---------|-------------|
|
|
165
|
+
| `gitmux init` | Create `.gitmux.yaml` in current dir (`--global` for `~/.gitmux.yaml`) |
|
|
166
|
+
| `gitmux add <url> --group <g>` | Add a repository (group auto-created) |
|
|
167
|
+
| `gitmux remove <name>` | Remove a repository |
|
|
168
|
+
| `gitmux list` | List all repositories |
|
|
169
|
+
| `gitmux status [target]` | Show git status overview (defaults to all) |
|
|
170
|
+
| `gitmux clone <target>` | Clone unclosed repositories |
|
|
171
|
+
| `gitmux fetch <target>` | Fetch remote data (`--branches` to list branches) |
|
|
172
|
+
| `gitmux pull <target>` | Pull latest changes |
|
|
173
|
+
| `gitmux push <target>` | Push local commits |
|
|
174
|
+
| `gitmux exec <cmd>` | Run command in repos (`--target` to specify) |
|
|
175
|
+
| `gitmux group list` | List groups |
|
|
176
|
+
| `gitmux group create <name>` | Create a group |
|
|
177
|
+
| `gitmux group remove <name>` | Remove a group |
|
|
178
|
+
|
|
179
|
+
### Target Syntax
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
gitmux pull map # repo 'map' in default group
|
|
183
|
+
gitmux pull base/map # repo 'map' in group 'base'
|
|
184
|
+
gitmux pull --group base # all repos in group 'base'
|
|
185
|
+
gitmux pull --all # all repos (explicit)
|
|
186
|
+
gitmux pull # error: specify target, --group, or --all
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Note: `gitmux add <url>` without `--group` places the repo in the `default` group.
|
|
190
|
+
|
|
191
|
+
### Common Options
|
|
192
|
+
|
|
193
|
+
- `--group, -g` — operate on entire group
|
|
194
|
+
- `--all, -a` — operate on all repositories (required for write operations without target)
|
|
195
|
+
- `--parallel, -p` — run in parallel (clone/fetch/pull/push/exec)
|
|
196
|
+
- `--config, -c` — custom config file path
|
|
197
|
+
|
|
198
|
+
## Development
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
git clone https://github.com/ryan/gitmux.git
|
|
202
|
+
cd gitmux
|
|
203
|
+
pip install -e ".[dev]"
|
|
204
|
+
pytest
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Code Quality
|
|
208
|
+
|
|
209
|
+
Uses [Ruff](https://docs.astral.sh/ruff/) for linting and formatting:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
ruff check . # lint
|
|
213
|
+
ruff check --fix . # auto-fix
|
|
214
|
+
ruff format . # format
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Rules: `E`, `F`, `W`, `I` (isort), `N`, `UP` (modern Python), `B` (bugbear), `SIM`.
|
|
218
|
+
|
|
219
|
+
## License
|
|
220
|
+
|
|
221
|
+
MIT
|
gitmux-0.1.0/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# gitmux
|
|
2
|
+
|
|
3
|
+
Manage multiple git repositories with ease. Clone, pull, push, and run commands across repos with a single command.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **YAML configuration** — declarative repo management
|
|
8
|
+
- **Group management** — organize repos into groups
|
|
9
|
+
- **Batch git operations** — clone/pull/push across repos
|
|
10
|
+
- **Pre/post hooks** — run commands before/after git operations (e.g., `npm install` after pull)
|
|
11
|
+
- **Template system** — share hook configs across similar repos
|
|
12
|
+
- **Parallel execution** — speed up operations with `--parallel` flag
|
|
13
|
+
- **Status overview** — see all repos' git status at a glance
|
|
14
|
+
- **Arbitrary command execution** — run any shell command across repos
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install gitmux
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Initialize config in current directory
|
|
26
|
+
gitmux init
|
|
27
|
+
|
|
28
|
+
# Add repos (default group if --group omitted)
|
|
29
|
+
gitmux add git@github.com:user/api-server.git --group backend
|
|
30
|
+
gitmux add git@github.com:user/auth-service.git --group backend
|
|
31
|
+
|
|
32
|
+
# Clone all repos
|
|
33
|
+
gitmux clone --all
|
|
34
|
+
|
|
35
|
+
# Pull a single repo
|
|
36
|
+
gitmux pull backend/api-server
|
|
37
|
+
|
|
38
|
+
# Pull entire group (parallel)
|
|
39
|
+
gitmux pull --group backend --parallel
|
|
40
|
+
|
|
41
|
+
# Check status of all repos
|
|
42
|
+
gitmux status
|
|
43
|
+
|
|
44
|
+
# Run command on a specific repo
|
|
45
|
+
gitmux exec "git checkout main" --target backend/api-server
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
Config file lookup order (used for both reading and writing):
|
|
51
|
+
1. `--config / -c` flag (explicit path)
|
|
52
|
+
2. `.gitmux.yaml` in current directory
|
|
53
|
+
3. `~/.gitmux.yaml` (global fallback)
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
workspace: ~/projects
|
|
57
|
+
|
|
58
|
+
templates:
|
|
59
|
+
node-app:
|
|
60
|
+
post_pull:
|
|
61
|
+
- npm install
|
|
62
|
+
pre_push:
|
|
63
|
+
- npm test
|
|
64
|
+
|
|
65
|
+
groups:
|
|
66
|
+
backend:
|
|
67
|
+
repos:
|
|
68
|
+
- name: api-server
|
|
69
|
+
url: git@github.com:user/api-server.git
|
|
70
|
+
template: node-app
|
|
71
|
+
- name: auth-service
|
|
72
|
+
url: git@github.com:user/auth-service.git
|
|
73
|
+
path: ~/custom/path/auth # override default path
|
|
74
|
+
hooks:
|
|
75
|
+
post_pull:
|
|
76
|
+
- pip install -r requirements.txt
|
|
77
|
+
frontend:
|
|
78
|
+
repos:
|
|
79
|
+
- name: web-app
|
|
80
|
+
url: git@github.com:user/web-app.git
|
|
81
|
+
template: node-app
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Path Resolution
|
|
85
|
+
|
|
86
|
+
- Default: `{workspace}/{group}/{repo_name}`
|
|
87
|
+
- Override per-repo with the `path` field
|
|
88
|
+
|
|
89
|
+
### Branch Management
|
|
90
|
+
|
|
91
|
+
Configure named branch aliases per repo:
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
repos:
|
|
95
|
+
- name: map
|
|
96
|
+
url: https://code.example.com/base/map.git
|
|
97
|
+
branches:
|
|
98
|
+
prod: "bInfinite-plan-*" # pattern (contains *)
|
|
99
|
+
dev: "bInfinite-dev-main" # fixed branch name
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Usage:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
gitmux pull map --branch dev # checkout fixed branch → pull
|
|
106
|
+
gitmux pull map --branch prod:latest # fetch → find newest matching branch → checkout → pull
|
|
107
|
+
gitmux pull map --branch prod:260515 # replace * → checkout bInfinite-plan-260515 → pull
|
|
108
|
+
gitmux pull --group base --branch dev # checkout fixed branch for all repos in group
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Rules:
|
|
112
|
+
- `--branch <alias>` — alias must be a fixed branch (no `*`), otherwise error
|
|
113
|
+
- `--branch <alias>:latest` — alias must be a pattern (has `*`), picks newest by commit date
|
|
114
|
+
- `--branch <alias>:<value>` — alias must be a pattern, replaces `*` with `<value>`
|
|
115
|
+
|
|
116
|
+
### Hook System
|
|
117
|
+
|
|
118
|
+
Hooks run shell commands before/after git operations:
|
|
119
|
+
|
|
120
|
+
- `pre_clone`, `post_clone`
|
|
121
|
+
- `pre_pull`, `post_pull`
|
|
122
|
+
- `pre_push`, `post_push`
|
|
123
|
+
|
|
124
|
+
**Error handling:**
|
|
125
|
+
- Pre-hook failure → git operation is skipped
|
|
126
|
+
- Post-hook failure → repo marked as failed
|
|
127
|
+
|
|
128
|
+
**Template merging:** Repo-level hooks override template hooks per hook type.
|
|
129
|
+
|
|
130
|
+
## Commands
|
|
131
|
+
|
|
132
|
+
| Command | Description |
|
|
133
|
+
|---------|-------------|
|
|
134
|
+
| `gitmux init` | Create `.gitmux.yaml` in current dir (`--global` for `~/.gitmux.yaml`) |
|
|
135
|
+
| `gitmux add <url> --group <g>` | Add a repository (group auto-created) |
|
|
136
|
+
| `gitmux remove <name>` | Remove a repository |
|
|
137
|
+
| `gitmux list` | List all repositories |
|
|
138
|
+
| `gitmux status [target]` | Show git status overview (defaults to all) |
|
|
139
|
+
| `gitmux clone <target>` | Clone unclosed repositories |
|
|
140
|
+
| `gitmux fetch <target>` | Fetch remote data (`--branches` to list branches) |
|
|
141
|
+
| `gitmux pull <target>` | Pull latest changes |
|
|
142
|
+
| `gitmux push <target>` | Push local commits |
|
|
143
|
+
| `gitmux exec <cmd>` | Run command in repos (`--target` to specify) |
|
|
144
|
+
| `gitmux group list` | List groups |
|
|
145
|
+
| `gitmux group create <name>` | Create a group |
|
|
146
|
+
| `gitmux group remove <name>` | Remove a group |
|
|
147
|
+
|
|
148
|
+
### Target Syntax
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
gitmux pull map # repo 'map' in default group
|
|
152
|
+
gitmux pull base/map # repo 'map' in group 'base'
|
|
153
|
+
gitmux pull --group base # all repos in group 'base'
|
|
154
|
+
gitmux pull --all # all repos (explicit)
|
|
155
|
+
gitmux pull # error: specify target, --group, or --all
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Note: `gitmux add <url>` without `--group` places the repo in the `default` group.
|
|
159
|
+
|
|
160
|
+
### Common Options
|
|
161
|
+
|
|
162
|
+
- `--group, -g` — operate on entire group
|
|
163
|
+
- `--all, -a` — operate on all repositories (required for write operations without target)
|
|
164
|
+
- `--parallel, -p` — run in parallel (clone/fetch/pull/push/exec)
|
|
165
|
+
- `--config, -c` — custom config file path
|
|
166
|
+
|
|
167
|
+
## Development
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
git clone https://github.com/ryan/gitmux.git
|
|
171
|
+
cd gitmux
|
|
172
|
+
pip install -e ".[dev]"
|
|
173
|
+
pytest
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Code Quality
|
|
177
|
+
|
|
178
|
+
Uses [Ruff](https://docs.astral.sh/ruff/) for linting and formatting:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
ruff check . # lint
|
|
182
|
+
ruff check --fix . # auto-fix
|
|
183
|
+
ruff format . # format
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Rules: `E`, `F`, `W`, `I` (isort), `N`, `UP` (modern Python), `B` (bugbear), `SIM`.
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
MIT
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "gitmux"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Manage multiple git repositories with ease"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "Ryan" }]
|
|
13
|
+
keywords = ["git", "multi-repo", "cli", "devtools"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Topic :: Software Development :: Version Control :: Git",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"typer>=0.15.4",
|
|
28
|
+
"rich>=13.9.4",
|
|
29
|
+
"pyyaml>=6.0.2",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest==8.3.4",
|
|
35
|
+
"pytest-mock==3.14.0",
|
|
36
|
+
"ruff==0.11.12",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.scripts]
|
|
40
|
+
gitmux = "gitmux.cli:app"
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/ryan/gitmux"
|
|
44
|
+
Repository = "https://github.com/ryan/gitmux"
|
|
45
|
+
Issues = "https://github.com/ryan/gitmux/issues"
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.wheel]
|
|
48
|
+
packages = ["src/gitmux"]
|
|
49
|
+
|
|
50
|
+
[tool.pytest.ini_options]
|
|
51
|
+
testpaths = ["tests"]
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
target-version = "py310"
|
|
55
|
+
line-length = 120
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
select = ["E", "F", "W", "I", "N", "UP", "B", "SIM"]
|
|
59
|
+
ignore = ["E501"]
|
|
60
|
+
|
|
61
|
+
[tool.ruff.lint.isort]
|
|
62
|
+
known-first-party = ["gitmux"]
|