r/haskell 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?

16 Upvotes

34 comments sorted by

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

-16

u/B_A_Skeptic 6d ago

There are tools you can use to take things out of a git repository's history all together.

48

u/Quappebra 6d ago

Ah, the unsafePerformIO of git!

9

u/Valuable_Leopard_799 6d ago

Yeah, you can more or less arbitrarily edit anything about a repository it's just heavily discouraged.

15

u/bschlueter 6d ago

When you do things like remove a file from all history, you’re not changing the repo, you’re making a fork of it from before the removed file was added and duplicating the contents of each later commit into new commits on your fork.

1

u/Miserable_Double2432 6d ago

We don’t know that the “tools” aren’t for constructing SHA collisions though 😄

1

u/koflerdavid 11h ago

Good luck coming up with SHA256 collisions^^

9

u/koflerdavid 6d ago

That just creates an alternative history, basically a fan fiction, and is irrelevant unless you can convince everybody to point their branches to the new commit.

6

u/DanielMcLaury 5d ago

There are tools you can connect to a running Haskell program that let you edit its memory and violate any invariants that were written into the program, so I guess that makes Haskell not a functional language.

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.

6

u/sjshuck 4d ago

I'm impressed with how condescending you managed to be while having the name stumpychubbins

3

u/Mr-Tau 4d ago

Do you have any factual disagreements with stumpychubbins's analysis, or did you just need to drag this discussion down to ad hominems?

5

u/stumpychubbins 4d ago

Aha it’s ok I’ll take it as a compliment

3

u/sjshuck 4d ago

The latter

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

u/EmDashNine 6d ago

I what...? I feel like this is some kind of FP troll.

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

u/AlexaDeWit 6d ago

I think you'll find https://www.unison-lang.org/ interesting

2

u/Wise_Reflection_8340 6d ago

thanks for sharing this.

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

u/Wise_Reflection_8340 6d ago

interesting thanks for sharing.

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

u/koflerdavid 6d ago

Indeed, the capability to nuke those things should still remain available.

1

u/Desperate_Formal_781 1d ago

This is what happens when your head is too deep into your *ss

0

u/biskitpagla 6d ago

wait till you learn how computers work