The index has to survive between commands, so Git writes it to a file. Real Git uses a packed binary format; we use a simple line-based one that is easy to read and round-trips cleanly. Today you save and load the index.
Write the index to disk and read it back into an identical index.
A staging area is only useful if it persists: you run add today, commit
tomorrow, and the index must still be there. Git serializes it to .mygit/index.
Real Git uses a compact binary format with cached stat data for speed; that
format is documented but fiddly, and it is not what this project is about, so we
use a plain line-based format instead: one line per entry with the mode, id,
and path, sorted by path.
This is the one place we knowingly diverge from real Git’s bytes. It is a safe
divergence: the index is a private staging structure, never hashed into an object,
so write-tree and every id downstream still match Git exactly. What must
round-trip is the information (each path’s mode and id), not the exact file
layout. Save it, load it, and confirm you get the same entries back.
// one line per entry: "<mode> <id> <path>\n", sorted by pathfor _, p := range ix.Paths() {e := ix.entries[p]fmt.Fprintf(w, "%s %s %s\n", e.Mode, e.Id, p)}// load: split each line into mode, id, path and Set it