detached 235a267

docs(git): describe phase A usage and checks

commit
235a2674e472335369f506dd7eb172859d30f3ea
author
brice · · 2026-10-10 20:35 UTC
parent
eb5a076
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +30 -2
M README.md +30 -2
@@ -2,18 +2,46 @@
22
33 A fast, read-only Git repository reader for Go: refs, objects, packfiles, trees and history, using commit-graph and changed-path Bloom filters. Standard library only.
44
5-Status: early development, no stable API.
5+Status: early development, no stable API. Phase A (this tree) reads refs, loose and packed objects, trees, blobs and commits; history walks come next.
66
77 ```go
88 import git "bnema.dev/ermite-git"
9+
10+repo, err := git.Open("/srv/repos/project.git") // bare, or a ".git" directory
11+if err != nil {
12+ return err // errors.Is(err, git.ErrUnsupported) → use the git binary
13+}
14+defer repo.Close()
15+
16+id, _ := repo.Resolve("main")
17+commitID, _ := repo.PeelToCommit(id)
18+
19+var c git.Commit // reuse it: no allocation per commit after warm-up
20+_ = repo.ReadCommit(commitID, &c)
21+_ = repo.ReadTree(c.Tree, func(e git.Entry) bool {
22+ fmt.Printf("%s %s\n", e.Mode, e.Name) // e.Name is valid during the callback only
23+ return true
24+})
925 ```
1026
27+A `Repo` is safe for concurrent use. Call `Refresh` after the repository changed (a push, a repack) to see new refs and packs; reads in flight keep working while packs are replaced.
28+
29+Repositories the package does not read are rejected by `Open` with `ErrUnsupported`: SHA-256, reftable, other `extensions.*`, shallow, grafts, replace refs, alternates, partial clones, incremental or stale multi-pack-index.
30+
1131 ## Test
1232
1333 ```sh
14-go test ./...
34+go test -race ./...
35+# also compare every object of a real repository with `git cat-file`:
36+ERMITE_GIT_BENCH_REPO=/path/to/repo/.git go test -run TestRealRepository -v
37+# benchmarks (the same variable runs them on that repository):
38+go test -run '^$' -bench . -benchmem
39+# fuzz targets:
40+go test -run '^$' -fuzz FuzzParseCommit -fuzztime 30s
1541 ```
1642
43+The tests build their fixtures with the `git` binary (2.45 or later) and compare with it.
44+
1745 ## License
1846
1947 MIT. See [LICENSE](LICENSE).
@@ -2,18 +2,46 @@
2 2
3 A fast, read-only Git repository reader for Go: refs, objects, packfiles, trees and history, using commit-graph and changed-path Bloom filters. Standard library only.3 A fast, read-only Git repository reader for Go: refs, objects, packfiles, trees and history, using commit-graph and changed-path Bloom filters. Standard library only.
4 4
5-Status: early development, no stable API.5+Status: early development, no stable API. Phase A (this tree) reads refs, loose and packed objects, trees, blobs and commits; history walks come next.
6 6
7 ```go7 ```go
8 import git "bnema.dev/ermite-git"8 import git "bnema.dev/ermite-git"
9+
10+repo, err := git.Open("/srv/repos/project.git") // bare, or a ".git" directory
11+if err != nil {
12+ return err // errors.Is(err, git.ErrUnsupported) → use the git binary
13+}
14+defer repo.Close()
15+
16+id, _ := repo.Resolve("main")
17+commitID, _ := repo.PeelToCommit(id)
18+
19+var c git.Commit // reuse it: no allocation per commit after warm-up
20+_ = repo.ReadCommit(commitID, &c)
21+_ = repo.ReadTree(c.Tree, func(e git.Entry) bool {
22+ fmt.Printf("%s %s\n", e.Mode, e.Name) // e.Name is valid during the callback only
23+ return true
24+})
9 ```25 ```
10 26
27+A `Repo` is safe for concurrent use. Call `Refresh` after the repository changed (a push, a repack) to see new refs and packs; reads in flight keep working while packs are replaced.
28+
29+Repositories the package does not read are rejected by `Open` with `ErrUnsupported`: SHA-256, reftable, other `extensions.*`, shallow, grafts, replace refs, alternates, partial clones, incremental or stale multi-pack-index.
30+
11 ## Test31 ## Test
12 32
13 ```sh33 ```sh
14-go test ./...34+go test -race ./...
35+# also compare every object of a real repository with `git cat-file`:
36+ERMITE_GIT_BENCH_REPO=/path/to/repo/.git go test -run TestRealRepository -v
37+# benchmarks (the same variable runs them on that repository):
38+go test -run '^$' -bench . -benchmem
39+# fuzz targets:
40+go test -run '^$' -fuzz FuzzParseCommit -fuzztime 30s
15 ```41 ```
16 42
43+The tests build their fixtures with the `git` binary (2.45 or later) and compare with it.
44+
17 ## License45 ## License
18 46
19 MIT. See [LICENSE](LICENSE).47 MIT. See [LICENSE](LICENSE).

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 2

↑↓ moveenter openesc close