Skip to content

Commit f05f2e3

Browse files
committed
docs(notes): add git command support audit 2025-11-26
why: Document current git command implementations and plan Manager pattern expansion for branch, remote, tag, stash, worktree, notes, submodule, reflog. what: - Audit existing GitBranchManager/GitBranchCmd methods - Audit existing GitRemoteManager/GitRemoteCmd methods - Document GitStashCmd and planned refactor to Manager pattern - Document GitSubmoduleCmd and planned refactor to Manager pattern - Plan new GitTagManager/GitTagCmd - Plan new GitWorktreeManager/GitWorktreeCmd - Plan new GitNotesManager/GitNoteCmd - Plan new GitReflogManager/GitReflogCmd
1 parent 5a60d3c commit f05f2e3

1 file changed

Lines changed: 373 additions & 0 deletions

File tree

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
# Git Command Support Audit - 2025-11-26
2+
3+
This document provides a comprehensive audit of git command support in libvcs, documenting existing implementations and planned additions following the Manager/Cmd pattern.
4+
5+
## Pattern Overview
6+
7+
```
8+
Manager (collection-level) Cmd (per-entity)
9+
├── ls() -> QueryList[Cmd] ├── run()
10+
├── get(**kwargs) -> Cmd | None ├── show()
11+
├── filter(**kwargs) -> list[Cmd] ├── remove()/delete()
12+
├── add() / create() ├── rename()
13+
└── run() └── entity-specific operations
14+
```
15+
16+
---
17+
18+
## 1. GitBranchManager / GitBranchCmd
19+
20+
**Pattern Status**: Implemented
21+
22+
### GitBranchManager (Collection-level)
23+
24+
| Method | Status | Description |
25+
|--------|--------|-------------|
26+
| `__init__(path, cmd)` | Implemented | Constructor |
27+
| `__repr__()` | Implemented | String representation |
28+
| `run(command, local_flags, quiet, cached)` | Implemented | Run git branch command |
29+
| `checkout(branch)` | Implemented | Checkout a branch |
30+
| `create(branch)` | Implemented | Create new branch via `checkout -b` |
31+
| `_ls()` | Implemented | Internal raw listing |
32+
| `ls()` | Implemented | Returns `QueryList[GitBranchCmd]` |
33+
| `get(**kwargs)` | Implemented | Get single branch by filter |
34+
| `filter(**kwargs)` | Implemented | Filter branches |
35+
36+
### GitBranchCmd (Per-entity)
37+
38+
| Method | Status | Description |
39+
|--------|--------|-------------|
40+
| `__init__(path, branch_name, cmd)` | Implemented | Constructor with `branch_name` |
41+
| `__repr__()` | Implemented | String representation |
42+
| `run(command, local_flags, quiet, cached)` | Implemented | Run git branch command |
43+
| `checkout()` | Implemented | Checkout this branch |
44+
| `create()` | Implemented | Create this branch |
45+
| `delete(force)` | **Missing** | `-d` / `-D` |
46+
| `rename(new_name, force)` | **Missing** | `-m` / `-M` |
47+
| `copy(new_name, force)` | **Missing** | `-c` / `-C` |
48+
| `set_upstream(upstream)` | **Missing** | `--set-upstream-to` |
49+
| `unset_upstream()` | **Missing** | `--unset-upstream` |
50+
| `track(remote_branch)` | **Missing** | `-t` / `--track` |
51+
52+
### GitBranchManager Enhancements Needed
53+
54+
| Feature | Status | Description |
55+
|---------|--------|-------------|
56+
| `--all` support | **Missing** | List all branches (local + remote) |
57+
| `--remotes` support | **Missing** | List remote branches only |
58+
| `--merged` filter | **Missing** | Filter merged branches |
59+
| `--no-merged` filter | **Missing** | Filter unmerged branches |
60+
| `--verbose` support | **Missing** | Show tracking info |
61+
62+
---
63+
64+
## 2. GitRemoteManager / GitRemoteCmd
65+
66+
**Pattern Status**: Implemented
67+
68+
### GitRemoteManager (Collection-level)
69+
70+
| Method | Status | Description |
71+
|--------|--------|-------------|
72+
| `__init__(path, cmd)` | Implemented | Constructor |
73+
| `__repr__()` | Implemented | String representation |
74+
| `run(command, local_flags)` | Implemented | Run git remote command |
75+
| `add(name, url, fetch, track, master, mirror)` | Implemented | Add new remote |
76+
| `show(name, verbose, no_query_remotes)` | Implemented | Show remotes |
77+
| `_ls()` | Implemented | Internal raw listing |
78+
| `ls()` | Implemented | Returns `QueryList[GitRemoteCmd]` |
79+
| `get(**kwargs)` | Implemented | Get single remote by filter |
80+
| `filter(**kwargs)` | Implemented | Filter remotes |
81+
82+
### GitRemoteCmd (Per-entity)
83+
84+
Properties: `remote_name`, `fetch_url`, `push_url`
85+
86+
| Method | Status | Description |
87+
|--------|--------|-------------|
88+
| `__init__(path, remote_name, fetch_url, push_url, cmd)` | Implemented | Constructor |
89+
| `__repr__()` | Implemented | String representation |
90+
| `run(command, local_flags, verbose)` | Implemented | Run git remote command |
91+
| `rename(old, new, progress)` | Implemented | Rename remote |
92+
| `remove()` | Implemented | Delete remote |
93+
| `show(verbose, no_query_remotes)` | Implemented | Show remote details |
94+
| `prune(dry_run)` | Implemented | Prune stale branches |
95+
| `get_url(push, _all)` | Implemented | Get remote URL |
96+
| `set_url(url, old_url, push, add, delete)` | Implemented | Set remote URL |
97+
| `set_branches(*branches, add)` | **Missing** | `set-branches` |
98+
| `set_head(branch, auto, delete)` | **Missing** | `set-head` |
99+
| `update(prune)` | **Missing** | `update` |
100+
101+
---
102+
103+
## 3. GitStashCmd (Current) → GitStashManager / GitStashEntryCmd (Planned)
104+
105+
**Pattern Status**: Not implemented - needs refactoring
106+
107+
### Current GitStashCmd
108+
109+
| Method | Status | Description |
110+
|--------|--------|-------------|
111+
| `__init__(path, cmd)` | Implemented | Constructor |
112+
| `__repr__()` | Implemented | String representation |
113+
| `run(command, local_flags, quiet, cached)` | Implemented | Run git stash command |
114+
| `ls()` | Implemented | List stashes (returns string) |
115+
| `push(path, patch, staged)` | Implemented | Push to stash |
116+
| `pop(stash, index, quiet)` | Implemented | Pop from stash |
117+
| `save(message, staged, keep_index, patch, include_untracked, _all, quiet)` | Implemented | Save to stash |
118+
119+
### Planned GitStashManager (Collection-level)
120+
121+
| Method | Status | Description |
122+
|--------|--------|-------------|
123+
| `__init__(path, cmd)` | **Planned** | Constructor |
124+
| `run(command, local_flags)` | **Planned** | Run git stash command |
125+
| `ls()` | **Planned** | Returns `QueryList[GitStashEntryCmd]` |
126+
| `get(**kwargs)` | **Planned** | Get single stash by filter |
127+
| `filter(**kwargs)` | **Planned** | Filter stashes |
128+
| `push(message, path, patch, staged, keep_index, include_untracked)` | **Planned** | Push to stash |
129+
| `clear()` | **Planned** | Clear all stashes |
130+
131+
### Planned GitStashEntryCmd (Per-entity)
132+
133+
Properties: `index: int`, `branch: str`, `message: str`
134+
135+
Parse from: `stash@{0}: On master: my message`
136+
137+
| Method | Status | Description |
138+
|--------|--------|-------------|
139+
| `__init__(path, index, branch, message, cmd)` | **Planned** | Constructor |
140+
| `show(stat, patch)` | **Planned** | Show stash diff |
141+
| `apply(index)` | **Planned** | Apply without removing |
142+
| `pop(index)` | **Planned** | Apply and remove |
143+
| `drop()` | **Planned** | Delete this stash |
144+
| `branch(branch_name)` | **Planned** | Create branch from stash |
145+
146+
---
147+
148+
## 4. GitSubmoduleCmd (Current) → GitSubmoduleManager / GitSubmoduleCmd (Planned)
149+
150+
**Pattern Status**: Not implemented - needs refactoring
151+
152+
### Current GitSubmoduleCmd
153+
154+
| Method | Status | Description |
155+
|--------|--------|-------------|
156+
| `__init__(path, cmd)` | Implemented | Constructor |
157+
| `__repr__()` | Implemented | String representation |
158+
| `run(command, local_flags, quiet, cached)` | Implemented | Run git submodule command |
159+
| `init(path)` | Implemented | Initialize submodules |
160+
| `update(path, init, force, checkout, rebase, merge, recursive, _filter)` | Implemented | Update submodules |
161+
162+
### Planned GitSubmoduleManager (Collection-level)
163+
164+
| Method | Status | Description |
165+
|--------|--------|-------------|
166+
| `__init__(path, cmd)` | **Planned** | Constructor |
167+
| `run(command, local_flags)` | **Planned** | Run git submodule command |
168+
| `ls()` | **Planned** | Returns `QueryList[GitSubmoduleCmd]` |
169+
| `get(**kwargs)` | **Planned** | Get single submodule by filter |
170+
| `filter(**kwargs)` | **Planned** | Filter submodules |
171+
| `add(url, path, branch, name, force)` | **Planned** | Add submodule |
172+
| `foreach(command, recursive)` | **Planned** | Execute in each submodule |
173+
| `sync(recursive)` | **Planned** | Sync submodule URLs |
174+
| `summary(commit, files, cached)` | **Planned** | Summarize changes |
175+
176+
### Planned GitSubmoduleCmd (Per-entity)
177+
178+
Properties: `name`, `path`, `url`, `branch`
179+
180+
| Method | Status | Description |
181+
|--------|--------|-------------|
182+
| `__init__(path, name, submodule_path, url, branch, cmd)` | **Planned** | Constructor |
183+
| `init()` | **Planned** | Initialize this submodule |
184+
| `update(init, force, checkout, rebase, merge, recursive)` | **Planned** | Update this submodule |
185+
| `deinit(force)` | **Planned** | Unregister submodule |
186+
| `set_branch(branch)` | **Planned** | Set branch |
187+
| `set_url(url)` | **Planned** | Set URL |
188+
| `status()` | **Planned** | Show status |
189+
| `absorbgitdirs()` | **Planned** | Absorb gitdir |
190+
191+
---
192+
193+
## 5. GitTagManager / GitTagCmd (New)
194+
195+
**Pattern Status**: Not implemented
196+
197+
### Planned GitTagManager (Collection-level)
198+
199+
| Method | Status | Description |
200+
|--------|--------|-------------|
201+
| `__init__(path, cmd)` | **Planned** | Constructor |
202+
| `run(command, local_flags)` | **Planned** | Run git tag command |
203+
| `ls(pattern, sort, contains, no_contains, merged, no_merged)` | **Planned** | Returns `QueryList[GitTagCmd]` |
204+
| `get(**kwargs)` | **Planned** | Get single tag by filter |
205+
| `filter(**kwargs)` | **Planned** | Filter tags |
206+
| `create(name, ref, message, annotate, sign, force)` | **Planned** | Create tag |
207+
208+
### Planned GitTagCmd (Per-entity)
209+
210+
Properties: `tag_name`, `ref`, `message` (for annotated)
211+
212+
| Method | Status | Description |
213+
|--------|--------|-------------|
214+
| `__init__(path, tag_name, ref, message, cmd)` | **Planned** | Constructor |
215+
| `show()` | **Planned** | Show tag details |
216+
| `delete()` | **Planned** | Delete tag (`-d`) |
217+
| `verify()` | **Planned** | Verify signed tag (`-v`) |
218+
219+
---
220+
221+
## 6. GitWorktreeManager / GitWorktreeCmd (New)
222+
223+
**Pattern Status**: Not implemented
224+
225+
### Planned GitWorktreeManager (Collection-level)
226+
227+
| Method | Status | Description |
228+
|--------|--------|-------------|
229+
| `__init__(path, cmd)` | **Planned** | Constructor |
230+
| `run(command, local_flags)` | **Planned** | Run git worktree command |
231+
| `ls()` | **Planned** | Returns `QueryList[GitWorktreeCmd]` |
232+
| `get(**kwargs)` | **Planned** | Get single worktree by filter |
233+
| `filter(**kwargs)` | **Planned** | Filter worktrees |
234+
| `add(path, branch, detach, checkout, lock, force)` | **Planned** | Add worktree |
235+
| `prune(dry_run, verbose, expire)` | **Planned** | Prune worktrees |
236+
237+
### Planned GitWorktreeCmd (Per-entity)
238+
239+
Properties: `worktree_path`, `branch`, `head`, `locked`, `prunable`
240+
241+
| Method | Status | Description |
242+
|--------|--------|-------------|
243+
| `__init__(path, worktree_path, branch, head, locked, prunable, cmd)` | **Planned** | Constructor |
244+
| `remove(force)` | **Planned** | Remove worktree |
245+
| `lock(reason)` | **Planned** | Lock worktree |
246+
| `unlock()` | **Planned** | Unlock worktree |
247+
| `move(new_path)` | **Planned** | Move worktree |
248+
| `repair()` | **Planned** | Repair worktree |
249+
250+
---
251+
252+
## 7. GitNotesManager / GitNoteCmd (New)
253+
254+
**Pattern Status**: Not implemented
255+
256+
### Planned GitNotesManager (Collection-level)
257+
258+
| Method | Status | Description |
259+
|--------|--------|-------------|
260+
| `__init__(path, cmd)` | **Planned** | Constructor |
261+
| `run(command, local_flags)` | **Planned** | Run git notes command |
262+
| `ls(ref)` | **Planned** | Returns `QueryList[GitNoteCmd]` |
263+
| `get(**kwargs)` | **Planned** | Get single note by filter |
264+
| `filter(**kwargs)` | **Planned** | Filter notes |
265+
| `add(object, message, file, force, allow_empty)` | **Planned** | Add note |
266+
| `prune(dry_run, verbose)` | **Planned** | Prune notes |
267+
| `merge(notes_ref, strategy, commit, abort, quiet)` | **Planned** | Merge notes |
268+
| `get_ref()` | **Planned** | Get notes ref |
269+
270+
### Planned GitNoteCmd (Per-entity)
271+
272+
Properties: `object`, `note_ref`
273+
274+
| Method | Status | Description |
275+
|--------|--------|-------------|
276+
| `__init__(path, object, note_ref, cmd)` | **Planned** | Constructor |
277+
| `show()` | **Planned** | Show note |
278+
| `edit()` | **Planned** | Edit note (non-interactive) |
279+
| `append(message)` | **Planned** | Append to note |
280+
| `copy(from_object)` | **Planned** | Copy note |
281+
| `remove()` | **Planned** | Remove note |
282+
283+
---
284+
285+
## 8. GitReflogManager / GitReflogCmd (New)
286+
287+
**Pattern Status**: Not implemented
288+
289+
### Planned GitReflogManager (Collection-level)
290+
291+
| Method | Status | Description |
292+
|--------|--------|-------------|
293+
| `__init__(path, cmd)` | **Planned** | Constructor |
294+
| `run(command, local_flags)` | **Planned** | Run git reflog command |
295+
| `ls(ref)` | **Planned** | Returns `QueryList[GitReflogCmd]` |
296+
| `get(**kwargs)` | **Planned** | Get single entry by filter |
297+
| `filter(**kwargs)` | **Planned** | Filter entries |
298+
| `expire(ref, _all, dry_run, rewrite, updateref, stale_fix, verbose)` | **Planned** | Expire entries |
299+
| `exists(ref)` | **Planned** | Check if reflog exists |
300+
301+
### Planned GitReflogCmd (Per-entity)
302+
303+
Properties: `ref`, `index`, `action`, `message`, `sha`
304+
305+
Parse from: `abc1234 HEAD@{0}: commit: message`
306+
307+
| Method | Status | Description |
308+
|--------|--------|-------------|
309+
| `__init__(path, ref, index, action, message, sha, cmd)` | **Planned** | Constructor |
310+
| `show()` | **Planned** | Show entry details |
311+
| `delete()` | **Planned** | Delete entry |
312+
313+
---
314+
315+
## Git Class Exposure
316+
317+
### Current
318+
319+
```python
320+
class Git:
321+
submodule: GitSubmoduleCmd
322+
remotes: GitRemoteManager # ✓ Manager pattern
323+
stash: GitStashCmd
324+
branches: GitBranchManager # ✓ Manager pattern
325+
```
326+
327+
### Planned
328+
329+
```python
330+
class Git:
331+
submodules: GitSubmoduleManager # Renamed + Manager pattern
332+
remotes: GitRemoteManager # ✓ Already done
333+
stash: GitStashManager # Refactored to Manager pattern
334+
branches: GitBranchManager # ✓ Already done
335+
tags: GitTagManager # New
336+
worktrees: GitWorktreeManager # New
337+
notes: GitNotesManager # New
338+
reflog: GitReflogManager # New
339+
```
340+
341+
---
342+
343+
## Implementation Order
344+
345+
1. Complete GitBranchCmd (add missing methods)
346+
2. Complete GitRemoteCmd (add missing methods)
347+
3. Implement GitTagManager/GitTagCmd
348+
4. Refactor GitStashCmd → GitStashManager/GitStashEntryCmd
349+
5. Implement GitWorktreeManager/GitWorktreeCmd
350+
6. Implement GitNotesManager/GitNoteCmd
351+
7. Refactor GitSubmoduleCmd → GitSubmoduleManager/GitSubmoduleCmd
352+
8. Implement GitReflogManager/GitReflogCmd
353+
9. Update Git class to expose all managers
354+
355+
---
356+
357+
## Test Coverage
358+
359+
Currently **no direct unit tests** exist for:
360+
- GitBranchManager / GitBranchCmd
361+
- GitRemoteManager / GitRemoteCmd
362+
- GitStashCmd
363+
- GitSubmoduleCmd
364+
365+
Tests use pytest fixtures from `libvcs.pytest_plugin`:
366+
- `create_git_remote_repo` - Creates temporary git repo
367+
- `git_repo` - Pre-made GitSync instance
368+
- `example_git_repo` - Example repo for doctests
369+
370+
All new tests will:
371+
- Use real git commands (no mocks)
372+
- Use pytest fixtures for setup/teardown
373+
- Follow TDD approach

0 commit comments

Comments
 (0)