Structural version control. Merges functions, not lines.
Git treats source files as bags of lines. Two developers add different functions to the same file — conflict. Both add different imports — conflict. One renames a variable, another adds a function nearby — conflict. None of these are real conflicts.
got is a standalone version control system that decomposes source into structural entities via gotreesitter — functions, methods, classes, imports — and merges at that level. Independent additions merge cleanly. Import blocks get set-union merged. Only genuine semantic overlaps produce conflicts.
# Git: CONFLICT (both modified main.go)
# Got: clean merge — two independent functions added
$ got merge feature
merging feature into main...
main.go: clean
merge completed cleanly
Got parses every source file into an ordered list of entities:
| Entity kind | Examples |
|---|---|
| Preamble | package main, license headers |
| Import block | import (...), from x import y |
| Declaration | Functions, methods, types, classes, structs, traits |
| Interstitial | Whitespace and comments between declarations |
Each entity has an identity key (e.g. decl:function_definition::ProcessOrder) that survives editing, reordering, and branch divergence. Merge operates on these identities instead of line numbers:
- Unchanged — keep as-is
- Modified by one side — take the modification
- Modified identically by both — no conflict
- Modified differently by both — diff3 fallback on that entity's body
- Import blocks — set-union merge (combine all imports, deduplicate)
- Added by one side — insert at correct position
- Deleted by one side, unchanged by other — remove
- Deleted vs modified — real conflict
The critical invariant: reconstructing entities always reproduces the original source byte-for-byte.
go install github.com/odvcencio/got/cmd/got@latestRequires Go 1.25+. Pure Go, no C dependencies.
Got follows the same mental model as Git:
# Initialize a repository
got init myproject
cd myproject
# Stage and commit
echo 'package main
func Hello() {}
' > main.go
got add main.go
got commit -m "initial commit"
# Branch and diverge
got branch feature
got checkout feature
# ... add func Goodbye() ...
got add main.go
got commit -m "add Goodbye"
# Back to main, make a different change
got checkout main
# ... add func Greet() ...
got add main.go
got commit -m "add Greet"
# Structural merge — no conflict
got merge featuregot init [path] Create a new repository
got add <files...> Stage files for commit
got reset [paths...] Unstage paths (restore index from HEAD)
got rm [--cached] <paths...> Remove paths from index and/or working tree
got status Show working tree status
got commit -m <message> Record changes
got log [--oneline] [-n N] Show commit history
got show [commit-ish] Show commit metadata and changed files
got blame [path] Show structural blame for a file
got diff [--staged] [--entity] Show changes
got branch [name] [-d name] List, create, or delete branches
got tag [name] List, create, or delete tags
got checkout <target> [-b] Switch branches
got merge <branch> Three-way structural merge
got cherrypick-entity ... Apply entity-scoped changes from another commit
got remote Manage remotes
got publish [owner/repo] Create remote repo on Gothub, set origin, and push
got clone <url> [dir] Clone from Got protocol endpoint
got pull [remote] [branch] Fetch and fast-forward local branch
got push [remote] [branch] Push local branch to remote
got reflog Show local ref update history
got gc Pack loose objects and prune unreachable data
got verify Verify repository object integrity
Use gothub:owner/repo instead of full URLs:
got remote add origin gothub:alice/demo
got clone gothub:alice/demo
got publish alice/demoGit forge shorthand is also supported:
got clone github:owner/repo
got clone gitlab:group/subgroup/repo
got clone bitbucket:workspace/repoFor Git-forge clones, got bootstraps a local .got repository from the cloned Git HEAD snapshot.
For self-hosted instances, set GOT_GOTHUB_URL:
export GOT_GOTHUB_URL=https://code.example.com
got remote add origin gothub:alice/demoWhen a remote is a Git forge URL, got routes clone/pull/push through Git transport; Gothub remotes continue to use native Got transport.
got clone from a Git forge bootstraps .got from the cloned Git HEAD snapshot so structural workflows can start immediately.
# Line-level diff (default)
got diff
# Entity-level diff — shows which functions/types changed
got diff --entity.got/
HEAD ref: refs/heads/main
objects/ SHA-256 content-addressed store (2-char fan-out)
refs/heads/ Branch tips
index Staging area
Object types: blob, entity, entitylist, tree, commit
Hashing: SHA-256 with type-length envelope (type len\0content)
| Package | Purpose |
|---|---|
pkg/object |
Content-addressed store with atomic writes |
pkg/entity |
Tree-sitter entity extraction and reconstruction |
pkg/diff3 |
Myers diff + three-way line merge |
pkg/diff |
Entity-level diff computation |
pkg/merge |
Structural three-way merge orchestrator |
pkg/repo |
Repository operations (init, commit, branch, checkout, merge) |
Got uses gotreesitter, a pure-Go tree-sitter runtime with 205 embedded grammars. Entity extraction is tested against:
- Go
- Python
- Rust
- TypeScript
- C
Any language with a tree-sitter grammar can be parsed. Declaration classification is extensible via node type maps.
Active development. 300+ tests passing across core packages. Structural merge is production-grade for supported scenarios, with pack files, object verification, remote sync, and entity-aware history workflows.
What exists:
- Content-addressed object store (SHA-256)
- Entity extraction via tree-sitter (205 languages)
- Three-way structural merge with entity-level resolution
- Set-union import merging
- Entity-level and line-level diff
- Pack files with delta support (
got gc) and repository verification (got verify) - Full CLI: init, add, reset, rm, status, commit, log, show, blame, diff, branch, tag, checkout, merge, cherrypick-entity, remote, publish, clone, pull, push, reflog, gc, verify
.gotignoresupport
What doesn't exist yet:
- Stash workflow
- Rebase/cherry-pick (commit-level porcelain)
- SSH transport for remotes
- Submodules
- gotreesitter — Pure-Go tree-sitter runtime (205 languages, no CGo)
- cobra — CLI framework
MIT