- git clone itself in a subfolder
- git checkout and build the initial D compiler
- install it in a temporary prefix
- git checkout the first breaking commit and build it with the initial compiler
- install it over the previous compiler
- git checkout ...
and so on. In normal operation all these stages would be cached, so before I abandoned this approach, I think I was up to a hundred or so intermediate versions.
Eventually I started doing git releases, which needed a better solution. So since I have an optional C backend, I just build the compiler with the C backend, then zip up all the C files to make the release. Then to bootstrap from it, I just do (effectively) gcc *.c -o build/neat_bootstrap.
edit: Ah, here it is: https://github.com/Neat-Lang/neat/blob/v0.1.6/bootstrap.sh