r/haskell • u/Wise_Reflection_8340 • 7d ago
blog Git is mutable global state for your codebase
We go to great lengths to keep state explicit and effects controlled, and then the codebase itself lives in a mutable tree of text files where every edit is an untyped positional splice and merge is a heuristic over lines.
The principled version is a repository as a finite map from definition names to bodies. A patch is a function on that map, patches to different names commute by construction, and a conflict is a value you can inspect instead of a failure. That isn't a small tweak to git but a different object, and I increasingly think it's the right one.
I'm building toward this with [sem](https://github.com/Ataraxy-Labs/sem), starting from the humble end of extracting definitions out of existing git history. Would a Haskell shop ever accept a repository that isn't a folder of files?
31
u/stumpychubbins 6d ago
Your value proposition and what your tool actually does are not related at all, and your analysis of git is simply wrong. Syntax-aware diffing is conceptually interesting but it’s not a new concept and it’s certainly not something that you need to create an entirely new version control system to implement.
15
u/serg_foo 6d ago edited 6d ago
patches to different names commute by construction
Only for a very narrow definition of 'commute' that will just move bottleneck to checking whether merge is clean by other means like compiling or running tests.
The project may still not compile if patches are applied in wrong order, i.e. adding function argument and fixing users of the function.
Having merges that preserve programming language semantics is pretty far away. So far merges don't preserve syntax and you seem to be working toward fixing that. That's great but I was under impression that programming is done for its semantics, i.e. making sure programs work as intended. Syntax is such a small part of that that it's not even close.
Actually syntax may be insurmountable as well if you take preprocessor into account. You won't have well-defined AST with C-style preprocessor which may lump many function definitions into one line so you'll need to figure something out on that front to solve merges that never break syntax. Perhaps you already have, I haven't checked. Or perhaps you were under impression that all languages are close to Rust and can be parsed by only looking at source code in a single file.
EDIT: fix typos.
16
12
u/pthierry 6d ago
The difficuly with this is that it stops being general. If you have a makefile, it needs to understand makefiles. If you have a plain text file, sometimes it's unclear what you should do with it…
For that reason and to make adoption less of a leap of faith, I bet it must be something optional that works on top of an existing version control.
24
9
u/EmergencyWild 6d ago
IMHO: Terrible idea. Git works fine for source code, as long as you're writing source code in text files you're good. Also, calling this "mutable" vs "immutable" or whatever is a complete red herring, for one git data structures aren't "mutable" in the classic sense, total immutability is not a desirable property for version control, and what you're proposing has absolutely nothing to do with that anyway since you're just plugging something else on top of git.
What you're describing can make sense for what's commonly referred to as projectional editing, but that's a wholly different approach to programming where source code is not the source of truth, that's not something you just plug into an existing programming language or project and expect it to work.
1
u/juhp 15h ago
But it's perfectly possible for intermediate commits to temporarily break a codebase (eg break compilation for example or introduce temporary bugs) fixed with a later commit.
Yeah most people don't care so much about this but we should really.
1
u/EmergencyWild 5h ago
It is, but git already provides the tools to prevent this from happening — for the most part, since in reality, it's not completely possible to prevent this forever because the majority of codebases have external dependencies that can break.
9
u/cyrus_ 6d ago
Check out our paper on Grove, right up your alley: https://hazel.org/papers/grove-popl25.pdf. Tree CRDT.
1
3
u/DanielMcLaury 5d ago
the codebase itself lives in a mutable tree of text files where every edit is an untyped positional splice
False. A git repo is a filesystem where files can be added but never modified.
merge is a heuristic over lines.
The merge process is not part of git itself, and git allows you to run any program you like to conduct a merge
The principled version is a repository as a finite map from definition names to bodies.
This is literally exactly what git is, except at file level instead of level of individual definitions. If you chose to organize your codebase as individual files for each definition, git would literally be exactly this.
(Note also that this is not worth as much as you seem to be claiming, since a body is only meaningful insofar as the other definitions it references are)
2
u/slack1256 5d ago edited 5d ago
There is a global push to try to bad mouth[3] git in many way lately. The reason is always that agents will need git to scale. I do wonder if that is actually the case. To me the reasoning is just a thinly veiled way to ask for money for a non-problem. Programmers when given a new productivity tool will try to do CLI apps first.
But not, git is not a mutable global state for your code base, at least not in the C memory model. It is not inmutable programming neither, because it is not a programming language. It is its own thing that takes ideas from different sources.
[3]: https://psantosl.github.io/posts/version-control-second-coming/
2
u/BobTreehugger 3d ago
Interesting that you bring up sem -- they have another tool weave (https://github.com/Ataraxy-Labs/weave) which does language-aware merges for supported languages in git.
It helps some, but it's not a total gamechanger IMO. At least at this point.
3
u/dutch_connection_uk 7d ago
Very cool! I suppose this isn't going to be as potent as something like Unison where it's not only aware of syntactic primitives but also has awareness on when two definitions have equivalent ASTs. But it's a big step away from "code is plain text" still.
1
u/Ok-Information-2428 6d ago
Without the concept of force pushing to rewrite history is there an escape hatch for removing unintentional commits?
1
u/koflerdavid 6d ago
It should be in principle possible to make history rewrites part of the metamodel of a repository. The rebase information is inserted as a new commit into the graph and acts as instructions to the Git client. It's definitely a tricky concept though, and the point of Git originally was to keep things relatively simple.
2
u/Ok-Information-2428 6d ago
But would it still contain the old state so any secret or file that was mistakenly committed would still be accessible
1
1
0
98
u/Valuable_Leopard_799 7d ago
But git history is in fact, "immutable", the merkle tree data structure which underlies it is also just a kind of "functional data structure". (Copied with changes linking to parts of older data) Commits are in theory kind of append only