Experimenting with LLMs to Recreate Git
TL;DR – Quick Summary
- Experimenting with LLMs to rebuild Git-level software is one of the most honest stress tests you can run on AI coding tools, because Git’s expected behavior is precise and verifiable.
- Linus Torvalds wrote the original Git in about 10 days, according to XDA Developers (2026); getting an LLM to match even a subset of that output is a structurally different challenge involving context limits, cross-component consistency, and semantic correctness.
- A documented local attempt used Qwen3.6:27b_Q4_K_M to construct a Git-like version-control system, per XDA Developers (2026), confirming that mid-tier quantized models can handle basic VCS logic when given structured prompts.
- Decomposing the project into isolated units (commands, object store, refs, staging, history traversal) consistently produces better LLM output than monolithic prompts.
- Human review between each component implementation is not optional; accumulated correctness errors compound quickly when components begin to interact.
Experimenting with LLMs to recreate complex software like Git puts AI coding capabilities under conditions that generic benchmark tests rarely replicate. Git is not a simple script: it manages a content-addressable object store, three-way merges, reference chains, and pack files, all with behaviors that developers depend on being exact. When you ask an LLM to build something this precise, every gap in the model’s understanding of data structures and system semantics surfaces immediately. The experiment earns its time precisely because Git’s expected behavior is well-documented, its user-facing outputs are machine-verifiable, and failure modes are impossible to miss.
This article covers the design decisions, component breakdown, and prompting strategies that make an LLM-based Git reconstruction more than a curiosity. It maps what works, what consistently breaks, and what the experience tells practitioners about where AI coding tools are genuinely useful versus where they still require significant human scaffolding.
Quick Takeaways
- Ask the LLM for an architecture document and test suite before writing a single line of implementation code.
- Treat each Git command (init, add, commit, log, diff) as a separate, independent implementation unit with its own prompt session.
- Validate each component against real Git output using small shell comparison scripts before moving to the next component.
- Running a local quantized model gives you unlimited iteration cycles without rate limits, which matters considerably for a project this size.
Why Recreate Git with an LLM?
Git is an ideal reconstruction target for several reasons. It is bounded in scope: the core commands are well-known, the internal file formats are documented, and the observable behavior is easy to test with shell scripts. It is also genuinely difficult, involving a directed acyclic graph of commit objects, SHA-1-based content addressing, and a staging area that separates working tree state from committed state.
The historical context adds useful framing. According to XDA Developers (2026), Linus Torvalds wrote the original Git in about 10 days. That figure sets a human baseline: a single expert with deep systems knowledge, working intensively, produced a functional distributed VCS in under two weeks. Getting an LLM to cover even a reasonable subset of that scope is a meaningful test of AI coding capability.
Beyond the benchmark aspect, the exercise is practically useful. Teams regularly need lightweight internal VCS tools, educational implementations that expose Git internals to learners, or Git-compatible interfaces for specialized storage backends. Using an LLM to generate that kind of targeted, behavior-compatible implementation is exactly the scenario where AI coding tools should prove their worth. If the LLM can deliver reliable components with reasonable prompting discipline, the effort is justified. If it cannot, the failure modes tell you exactly what limitations to design around.
Git also benefits from a large body of community documentation. That documentation becomes the ground truth for evaluating LLM output: you can compare hashes, inspect the .git/ directory structure, and run standard Git commands against the reimplemented tool to see where behavior diverges. No fuzzy judgment required.
What Makes Git Difficult to Rebuild?
Git’s internal complexity comes from several interacting systems, each of which is individually manageable but collectively demanding.
The object model is the foundation. Git stores blobs (file content), trees (directory snapshots), commits (tree pointers plus metadata), and tags as SHA-1-addressed objects in a flat key-value store. Every object’s hash is computed from its content, so a single byte difference produces a completely different address. An LLM implementing this must get the binary serialization format exactly right, or the entire reference chain breaks.
The index (staging area) is a separate binary file that tracks the transition between working tree and committed state. Its format has evolved across Git versions and includes fields for file mode, modification timestamps, inode numbers, and merge stage information. Generating a correct index writer and reader from a prompt requires the LLM to hold a detailed binary protocol in context.
The reference system (HEAD, branches, remotes) is conceptually simple but introduces a large number of edge cases around symbolic refs, detached HEAD state, and ref update atomicity. Published research on managing LLM agent context using Git-like structures shows how Git’s reference semantics, when modeled abstractly, require careful state management that LLMs can handle inconsistently across long sessions.
Finally, merge resolution requires implementing a three-way merge algorithm that correctly identifies base commits, computes diffs, and resolves conflicts in a reproducible way. This is where most LLM-generated implementations either omit the feature entirely or produce a simplified version that fails on non-trivial conflict scenarios.
From what I have seen testing LLMs on repo-level tasks, models struggle more with cross-file and cross-component reasoning than with isolated function generation, which maps directly to what Git reconstruction exposes.
Designing the Experiment Architecture
Experimenting with LLMs on a project like Git requires upfront design discipline that most casual AI coding sessions skip. The first prompt should not ask for code. It should ask for an architecture.
A productive opening prompt looks like this: “You are going to help me implement a Git-compatible version-control system in Python. Before writing any implementation code, produce an architecture document that lists: (1) all data structures needed for the object store, index, and ref system; (2) the public interface for each module; (3) a list of test cases that would verify correct behavior against reference Git output.” This separates planning from implementation and forces the LLM to surface assumptions before they become bugs.
The architecture prompt also establishes a contract you can hold the model to in subsequent sessions. When an implementation diverges from the agreed design, you catch the drift early rather than after several components have been built on a faulty foundation.
One documented approach, reported by XDA Developers (2026), involved running Qwen3.6:27b_Q4_K_M locally to build a Git-like version-control system. Using a local model matters for this kind of extended experiment: you get unlimited iterations without hitting API rate limits, your intermediate code never leaves your machine, and you can run the model in a tight loop with shell-based validation scripts. Practitioners consistently find that tight human-AI iteration loops, with verification steps between each cycle, produce more reliable results than single long-context generation runs (see emerging LLM programming practices).
Breaking Git into Implementable Components
Once the architecture is agreed, the most effective approach is strict component isolation. Each component gets its own prompt session, its own output file, and its own verification step before you proceed.
A practical breakdown for a minimal but meaningful Git clone looks like this:
- Object store: SHA-1 computation, zlib compression, blob/tree/commit serialization and deserialization, loose object read and write.
- Index writer/reader: binary format for staging area, stat data handling, path encoding.
- Reference management: HEAD read/write, branch creation and update, symbolic ref resolution.
- Core commands:
init,hash-object,cat-file,update-index,write-tree,commit-tree,add,commit,log,diff,checkout. - History traversal: parent pointer walking for
log, common ancestor computation for merge base.
Each unit is small enough that the LLM can hold it in working context without degrading. When you then need to wire two components together, you pass the agreed interfaces from the architecture document rather than the full implementation, keeping the integration prompt clean.
In my own work with LLM dev workflows, I find fewer integration failures when breaking tasks into smaller units and verifying each output before continuing, rather than attempting large single-session generation.
python your_hash_object.py somefile and compare the output to git hash-object somefile. If the hashes match, the serialization is correct. This one-line check eliminates entire classes of downstream bugs before they propagate.Prompting Strategies for Repository-Scale Development
Experimenting with LLMs on repository-scale development surfaces a consistent set of prompting patterns that separate productive sessions from ones that produce plausible-looking but broken code.
Specify the interface contract first. Before asking for the implementation of any Git command, tell the model exactly what function signatures it must expose, what exceptions it should raise on error, and what it must NOT do (for example, touch the filesystem outside the designated repository directory). Ambiguity in the interface produces implementations that work in isolation but fail during integration.
Include the reference output inline. For hash-based operations, paste the actual bytes or hash values you expect from real Git. For command output, include the exact string format. LLMs that see the expected output treat it as a contract and generate more precise code than when asked to infer the format from prose description alone.
Explicitly request error handling. LLMs default to producing happy-path implementations. Git’s reliability comes from handling malformed objects, missing refs, and permission errors gracefully. Add a line to every implementation prompt: “Also implement error handling for: missing .git directory, corrupted object file, ref update race condition.”
Manage context decay. In long sessions, early design decisions drift out of the LLM’s effective context window. A Git-context control approach some practitioners describe offers a useful analogy: treat your architecture document as a HEAD commit that you re-inject at the start of each new session rather than relying on conversational memory.
Practical Application
The right starting point depends on your familiarity with Git internals and AI-assisted development.
Beginner: Scope to a single command. Ask the LLM to implement only git init and git hash-object, then verify the output by comparing SHA-1 hashes against reference Git. This gives you a complete feedback loop without committing to the full project scope.
Intermediate: Implement the object store and index writer as separate components using the architecture-first approach described in the Designing the Experiment section. After each component, run a comparison script that calls both your implementation and real Git on the same input and diffs the output. Only advance to the next component when this script passes cleanly.
Advanced: Wire completed components into a command dispatcher and test the full init / add / commit / log cycle end-to-end. At this stage, inject the architecture document at the start of each new session, ask the LLM to identify any interface mismatches before generating integration code, and run your growing test suite after every change. Use Qwen3.6:27b_Q4_K_M or a comparable local model to keep iteration speed high and intermediate outputs private.
The pattern across all tiers: verify before continuing. Each Git component depends on the correctness of the one beneath it, and an undetected bug in the object store will corrupt every commit written above it.
Experimenting with LLMs as a Git reconstruction tool ultimately teaches as much about effective AI prompting as it does about VCS internals. The models available today can handle individual components with real competence. The challenge is integration, state consistency, and correctness under edge-case conditions. Those are exactly the areas where human review remains essential, and where architecture-first, test-first prompting pays the most visible dividends. Any practitioner who wants an honest read on the genuine limits of AI coding tools should run this experiment: the failure modes are instructive, the working components are genuinely useful, and the gap between the two tells you precisely where to invest your review time.
Frequently Asked Questions
- Can an LLM build a working Git clone?
- Partially, yes. XDA Developers (2026) reported that running the local model Qwen3.6:27b_Q4_K_M produced a functional Git-like VCS covering core commands. The happy path works. Edge cases around merge conflict resolution, pack file generation, and ref integrity typically require targeted human fixes before the implementation can be called production-ready.
- Which Git features are hardest for an LLM to recreate?
- Three-way merge resolution and the binary index format are consistently the hardest. Both require the LLM to hold a precise, multi-field protocol in context and produce bit-for-bit correct output. The object store hashing is easier to verify and tends to come out cleanly; merge logic and stat-data handling in the index are where most attempts fall short.
- What prompts help an LLM implement complex software?
- Three practices make the biggest difference: asking for an architecture document before any code, specifying exact function signatures and expected outputs in every prompt, and explicitly requesting error handling for failure modes. Pasting reference output directly into the prompt, so the model treats it as a contract, also substantially improves precision over prose-only specifications.
- How do you evaluate software recreated by an LLM?
- Use Git’s own output as your oracle. Write small shell scripts that run the same operation against both real Git and your reimplemented tool, then diff the results. For hash-based operations, a single character difference in output is an unambiguous failure signal. This behavioral comparison approach catches regressions immediately without access to protected source code.
- What are the limitations of using LLMs to recreate Git?
- Context decay across long sessions is the primary structural limit: early design decisions drift out of the model’s effective working window, causing implementations to diverge from the agreed architecture. Beyond that, current models struggle with cross-component consistency and produce happy-path code by default. In practice, these gaps persist even in well-structured prompting workflows, particularly for tasks requiring cross-component state reasoning.