[HN Gopher] The future of version control
       ___________________________________________________________________
        
       The future of version control
        
       Author : c17r
       Score  : 641 points
       Date   : 2026-03-22 15:16 UTC (1 days ago)
        
 (HTM) web link (bramcohen.com)
 (TXT) w3m dump (bramcohen.com)
        
       | bos wrote:
       | This is sort of a revival and elaboration of some of Bram's ideas
       | from Codeville, an earlier effort that dates back to the early
       | 2000s Cambrian explosion of DVCS.
       | 
       | Codeville also used a weave for storage and merge, a concept that
       | originated with SCCS (and thence into Teamware and BitKeeper).
       | 
       | Codeville predates the introduction of CRDTs by almost a decade,
       | and at least on the face of it the two concepts seem like a
       | natural fit.
       | 
       | It was always kind of difficult to argue that weaves produced
       | unambiguously better merge results (and more limited conflicts)
       | than the more heuristically driven approaches of git, Mercurial,
       | et al, because the edit histories required to produce test cases
       | were difficult (at least for me) to reason about.
       | 
       | I like that Bram hasn't let go of the problem, and is still
       | trying out new ideas in the space.
        
         | dboreham wrote:
         | Note that CRDT isn't "a thing". The CRDT paper provides a way
         | to think about and analyze eventually consistent replication
         | mechanisms. So CRDTs weren't "introduced", only the "CRDT way
         | of discussing replication". Every concrete mechanism described
         | in the CRDT paper is very old, widely used for decades
         | beforehand.
         | 
         | This means that everything that implements eventual consistency
         | (including Git) is using "a CRDT".
        
           | hrmtst93837 wrote:
           | If you stretch "CRDT" to mean any old eventually consistent
           | thing, almost every Unix tool morphs into one under a loose
           | enough definition. That makes the term much less useful,
           | because practical CRDTs in 2024 usually mean opaque merge
           | semantics, awkward failure modes, and operational complexity
           | that has very little in common with the ancient algorithms
           | people point at when they say "Git is a CRDT too". "Just Git"
           | is doing a lot of work there.
        
           | mweidner wrote:
           | While this is technically correct, folks discussing CRDTs in
           | the context of text editing are typically thinking of a
           | fairly specific family of algorithms, in which each character
           | (or line) is assigned an immutable ID drawn from some
           | abstract total order. That is the sense in which the original
           | post uses the term (without mentioning a specific total
           | order).
        
         | gritzko wrote:
         | In 2007 Bram said to me that my Causal Tree algorithm is a
         | variant of weave. Which is broadly correct. In these 20 years,
         | the family of weave-class algos grew quite big. In my 2020
         | article, I devoted the intro to making their family portrait
         | https://arxiv.org/abs/2002.09511 Could have been a separate
         | article.
        
         | bramcohen wrote:
         | The whole point of using a proper CRDT is that it's easy to
         | reason about what it does. It took me a while to figure out the
         | details of how to build one.
        
       | logicprog wrote:
       | This seems like an excellent idea. I'm sure a lot of us have been
       | idly wondering why CRDTs aren't used for VCS for some time, so
       | it's really cool to see someone take a stab at it! We really do
       | need an improvement over git; the question is how to overcome
       | network effects.
        
         | righthand wrote:
         | Well over half of all people can't tell you the difference
         | between git and Github. The latter being owned by a corporation
         | that needs the network effect to keep existing.
        
         | vishvananda wrote:
         | This is actually a very interesting moment to potentially
         | overcome network effects, because more and more code is going
         | to be written by agents. If a crdt approach is measurably
         | better for merging by agent swarms then there is incentive to
         | make the switch. It also much easier to get an agent to change
         | its workflow than a human. The only tricky part is how much git
         | usage is in the training set so some careful thought would need
         | to be given to create a compatibility layer in the tooling to
         | help agents along.
        
         | NetOpWibby wrote:
         | Overcoming network effects cannot be the goal; otherwise, work
         | will never get done.
         | 
         | The goal should be to build a full spec and then build a code
         | forge and ecosystem around this. If it's truly great, adoption
         | will come. Microsoft doing a terrible job with GitHub is great
         | for new solutions.
        
       | ZoomZoomZoom wrote:
       | The key insight in the third sentence?
       | 
       | > ... CRDTs for version control, which is long overdue but hasn't
       | happened yet
       | 
       | Pijul happened and it has hundreds - perhaps thousands - of hours
       | of real expert developer's toil put in it.
       | 
       | Not that Bram is not one of those, but the post reads like you
       | all know what.
        
         | simonw wrote:
         | I hadn't heard of Pijul. My first search took me to
         | https://github.com/8l/pijul which hasn't been updated in 11
         | years, but it turns out that's misleading and the official repo
         | at https://nest.pijul.com/pijul/pijul had a commit last month.
         | 
         | ... and of course it is, because Pijul uses Pijul for
         | development, not Git and GitHub!
        
           | idoubtit wrote:
           | The canonical website is https://pijul.org. The homepage has
           | a link to the pijul source repository.
        
             | ozten wrote:
             | They should mirror on GitHub for marketing purposes
        
               | nicoty wrote:
               | How would they do that if they don't use git for version
               | control? Does GitHub allow other forms of version control
               | other than git?
        
               | simonw wrote:
               | SQLite does it despite using Fossil - their mirror is at
               | https://github.com/sqlite/sqlite
               | 
               | Git is so established now that it's sensible for
               | alternative VCS to have a mode where they can imitate the
               | Git protocol - or seven without that you can still
               | checkout the latest version of your repo and git push
               | that on a periodic basis.
        
               | verdverm wrote:
               | Similarly, CUE uses Gerrit and has two way sync. If you
               | are building a VCS today, git interop is a must.
        
               | adastra22 wrote:
               | What if the whole point of your VCS is that it its core
               | data structure is nothing like git's at all?
        
               | verdverm wrote:
               | As a user, why do I care how the internals work?
               | 
               | What I do care about is an easy path to progressive
               | adoption and migration. Without that, I cannot convince
               | my team / org to force everyone over.
        
               | adastra22 wrote:
               | Git is not a protocol, it is a data format. That only
               | makes sense when your VCS system is similar enough to git
               | to easily allow converting between the two
               | representations.
        
               | simonw wrote:
               | I mean things like git-svn, hg-git, git-p4, git-remote-
               | fossil, git-tfs, jj.
        
               | adastra22 wrote:
               | Every single one of those is following variations on the
               | exact same data structure, or is actually git in a
               | trenchcoat.
        
               | ozten wrote:
               | pijul clone https://nest.pijul.org/pijul/pijul
               | 
               | pijul log --hash-only > all_changes.txt
               | 
               | pijul unrecord --all
               | 
               | git init
               | 
               | ``` for HASH in $(cat all_changes.txt); do pijul apply
               | "$HASH" pijul reset # sync working copy to channel state
               | git add -A git commit -m "pijul change: $HASH" done ```
               | 
               | git remote add origin git@github.com:you/pijul-mirror.git
               | git push -u origin main
        
           | codethief wrote:
           | > I hadn't heard of Pijul
           | 
           | I'm surprised! Pijul has been discussed here on HN many, many
           | times. My impression is that many people here were hoping
           | that Pijul might eventually become a serious Git contender
           | but these days people seem to be more excited about Jujutsu,
           | likely because migration is much easier.
        
             | simonw wrote:
             | Looks like it makes the homepage only once or twice a year
             | (using points>50 as a proxy for that), had more buzz around
             | five years ago: https://hn.algolia.com/?dateRange=all&page=
             | 0&prefix=false&qu...
        
             | jedberg wrote:
             | I too am here all the time and have never heard of it. But
             | it looks interesting.
        
         | vova_hn2 wrote:
         | I have a weird hobby: about once a year I go to the theory page
         | [0] in pijul manual and see if they have fixed the TeX
         | formatting yet.
         | 
         | You would think that if a better, more sound model of storing
         | patches is _your whole selling point_ , you would want to make
         | as easy as possible for people who are interested in the
         | project to actually understand it. It is really _weird_ not to
         | care about the first impression that your manual makes on a
         | curious reader.
         | 
         | Currently, I'm about 6 years into the experiment.
         | 
         | Approximately 2 years in (about 4 years ago), I've actually
         | went to the Pijul Nest and reported [1] the issue. I got an
         | explanation on fixing this issue locally, but weirly enough,
         | the fix _still wasn 't actually implemented on the public
         | version_.
         | 
         | I'll report back in about a year with an update on the
         | experiment.
         | 
         | [0] https://pijul.org/manual/theory.html
         | 
         | [1] https://nest.pijul.com/pijul/manual/discussions/46
        
           | AceJohnny2 wrote:
           | > _It is really weird not to care about the first impression
           | that your manual makes on a curious reader._
           | 
           | On the contrary, I think this is an all-too-familiar pitfall
           | for the, er... technically minded.
           | 
           | "I've implemented it in the code. My work here is done. The
           | rest is window dressing."
        
           | oofbey wrote:
           | Hilarious. I agree that it says a lot how a project handles
           | reports like these.
        
           | onoesworkacct wrote:
           | I mean, I personally just saw some stuff inside dollar signs
           | and went "huh, weird choice of delimiter"
        
         | rbsmith wrote:
         | Do you use Pijul?
         | 
         | From time to time, I do a 'pijul pull -a' into the pijul source
         | tree, and I get a conflict (no local work on my part). Is there
         | a way to do a tracking update pull? I didn't see one, so I toss
         | the repo and reclone. What works for you in tracking what's
         | going on there?
        
           | adastra22 wrote:
           | From time to time I get curious about Pijul, attempt to pull
           | the Pijul repo from the nest, and encounter a no-workaround-
           | possible bug in the network sync. I have never been able to
           | do a fresh clone of Pijul.
           | 
           | It is very hard to take a project like this seriously.
        
         | mkj wrote:
         | Are you saying Bram hasn't worked on VCS problems much?
         | https://web.archive.org/web/20071213090008/http://codeville....
         | is 20 years.
        
         | zamalek wrote:
         | Pijul isn't a CRDT is it? It's theory of patches (i.e. DARCS++)
         | alongside native conflicts.
        
           | gnufx wrote:
           | Its author says it implements a CRDT in its theory
           | documentation.
        
       | radarsat1 wrote:
       | Is it a good thing to have merges that never fail? Often a merge
       | failure indicates a semantic conflict, not just "two changes in
       | the same place". You want to be aware of and forced to manually
       | deal with such cases.
       | 
       | I assume the proposed system addresses it somehow but I don't see
       | it in my quick read of this.
        
         | mikey-k wrote:
         | This
        
         | recursivecaveat wrote:
         | It says that merges that involve overlap get flagged to the
         | user. I don't think that's much more than a defaults difference
         | to git really. You could have a version of git that just warns
         | on conflict and blindly concats the sides.
        
         | hungryhobbit wrote:
         | They address this; it's not that they don't fail, in
         | practice...
         | 
         | the key insight is that changes should be flagged as
         | conflicting when they touch each other, giving you informative
         | conflict presentation on top of a system which never actually
         | fails.
        
           | bigfishrunning wrote:
           | Isn't that how the current systems work though? Git inserts
           | conflict markers in the file, and then emacs (or whatever
           | editor) highlights them
           | 
           | The big red block seems the same as "flagged", unless I'm
           | misunderstanding something
        
             | computably wrote:
             | With git, conflicts interrupt the merge/rebase. And if you
             | end up in a situation with multiple rebases/merges/both,
             | it's easy to get a "bad" state, or be forced to resolve
             | redundant conflict(s) over and over.
             | 
             | In Jujutsu and Pijul, for example, conflicts are recorded
             | by default but marked as conflict commits/changes. You can
             | continue to make commits/changes on top. Once you resolve
             | the conflict of A+B, no future merges or rebases would
             | cause the same conflict again.
        
               | bigfishrunning wrote:
               | Thank you for the explanation, i did misunderstand! seems
               | like a neat feature
        
         | rectang wrote:
         | I agree. Nevertheless I wonder if this approach can help with
         | certain other places where Git sometimes struggles, such as
         | whether or not two commits which have identical diffs but
         | different parents should be considered equivalent.
         | 
         | In the general case, such commits cannot be considered the same
         | -- consider a commit which flips a boolean that one branch had
         | flipped in another file. But there are common cases where the
         | commits should be considered equivalent, such as many rebased
         | branches. Can the CRDT approach help with e.g. deciding that
         | `git branch -d BRANCH` should succeed when a rebased version of
         | BRANCH has been merged?
        
         | gojomo wrote:
         | Should you be counting on confusion of an underpowered text-
         | merge to catch such problems?
         | 
         | It'll fire on merge issues that aren't code problems under a
         | smarter merge, while also missing all the things that merge OK
         | but introduce deeper issues.
         | 
         | Post-merge syntax checks are better for that purpose.
         | 
         | And imminently: agent-based sanity-checks of preserved intent -
         | operating on a logically-whole result file, without merge-tool
         | cruft. Perhaps at higher intensity when line-overlaps - or even
         | more-meaningful hints of cross-purposes - are present.
        
           | skydhash wrote:
           | > It'll fire on merge issues that aren't code problems under
           | a smarter merge, while also missing all the things that merge
           | OK but introduce deeper issues.
           | 
           | That has not been my experience at all. The changes you
           | introduced is your responsibility. If you synchronizes your
           | working tree to the source of truth, you need to evaluate
           | your patch again whether it introduces conflict or not. In
           | this case a conflict is a nice signal to know where someone
           | has interacted with files you've touched and possibly change
           | their semantics. The pros are substantial, and it's quite
           | easy to resolve conflicts that's only due to syntastic
           | changes (whitespace, formatting, equivalent statement,...)
        
             | gojomo wrote:
             | If you're relying on a serialized 'source of truth',
             | against which everyone must independently ensure their
             | changes sanely apply in isolation, the. you've already
             | resigned yourself to a single-threaded process that's
             | slower than what improved merges aim to enable.
             | 
             | Sure, that works - like having one (rare, expensive) savant
             | engineer apply & review everything in a linear canonical
             | order. But that's not as competitive & scalable as flows
             | more tolerant of many independent coders/agents.
        
               | yammosk wrote:
               | And yet after all these year of git supporting no source
               | of truth we still fall back on it. As long as you have an
               | authoritative version and authoritative release then you
               | have one source of truth. Linus imagined everyone
               | contributing with no central authority and yet we look to
               | GitHub and Gitlab to centralize our code. Git is already
               | decentralized and generally we find it impractical.
        
               | skydhash wrote:
               | Decentralization in this case means one can secede easily
               | from the central authority. So anyone working on a
               | project can easily split away from the main group at any
               | time. But every project have a clear governance where the
               | main direction is set and the canonical version of the
               | thing being under version control is stored.
               | 
               | That canonical version is altered following a process and
               | almost every project agrees that changes should be
               | proposed against it. Even with independent agents, there
               | should be a way to ensure consensus and decides the final
               | version. And that problem is a very hard one.
        
             | IshKebab wrote:
             | He's not saying you shouldn't have conflicts; just that
             | it's better to have syntax-aware conflict detection. For
             | example if two people add a new function to the end of the
             | same file, Git will always say that's a conflict. A syntax-
             | aware system could say that they don't conflict.
        
           | radarsat1 wrote:
           | > Should you be counting on confusion of an underpowered
           | text-merge to catch such problems?
           | 
           | This does not really follow from my statement.
           | 
           | I said that underpowered text merge should not _silently
           | accept_ such situations, not that it is the only way to catch
           | them. It doesn 't replace knowing something about what you
           | are merging, but it is certainly a good hint that something
           | may be wrong or unexpected.
           | 
           | > Post-merge syntax checks are better for that purpose.
           | 
           | Better, yes, but I was addressing _semantic_ issues, not
           | syntactical. I have seen syntactically valid merges result in
           | semantic inconsistency, it does happen.
           | 
           | I do agree with your last statement.. unit & integration
           | tests, agent checks or whathaveyou, these all contribute to
           | _semantic_ checking, which is a good thing.
           | 
           | Can they be relied on here? Maybe? I guess the jury is still
           | out. My testing philosophy is "you can only test for what you
           | think of testing". And tests and agent checks have a signal
           | to noise ratio, and are only as useful as their SNR allows.
           | 
           | There is no guaranteed way to stop bugs from happening, if
           | there were it likely would have been discovered by now. All
           | we can do is take a layered approach to provide opportunities
           | for them to get caught early. Removing one of those layers
           | (merge conflicts) is not clearly a good thing, imho, but who
           | knows.. if agent checks can replace it, then sure, I'm all
           | for it.
        
         | jwilliams wrote:
         | Indeed. And plenty of successful merges end up with code that
         | won't compile.
         | 
         | FWIW I've struggled to get AI tools to handle merge conflicts
         | well ( _especially rebase_ ) for the same underlying reason.
        
           | layer8 wrote:
           | Code not compiling is still the good case, because you'll
           | notice before deployment. The dangerous cases are when it
           | does compile.
        
             | jwilliams wrote:
             | Very true.
             | 
             | I realized recently that I've subconsciously routed-around
             | merge conflicts as much as possible. My process has just
             | subtly altered to make them less likely. To the point of
             | which seeing a 3-way merge feels jarring. It's really only
             | taking on AI tools that bought this to my attention.
        
             | Gibbon1 wrote:
             | I've seen merged code where the memory barriers were
             | misplaced.
        
           | skydhash wrote:
           | I'm surprised to see that some people sync their working tree
           | and does not evaluate their patch again (testing and
           | reviewing the assumptions they have made for their changes).
        
         | conradludgate wrote:
         | My understanding of the way this is presented is that merges
         | don't _block_ the workflow. In git, a merge conflict is a
         | failure to merge, but in this idea a merge conflict is still
         | present but the merge still succeeds. You can commit with
         | conflicts unresolved. This allows you to defer conflict
         | resolution to later. I believe jj does this as well?
         | 
         | Technically you could include conflict markers in your commits
         | but I don't think people like that very much
        
           | rightbyte wrote:
           | > You can commit with conflicts unresolved.
           | 
           | True but it is not valid syntax. Like, you mean with the
           | conflict lines?
        
             | ericpauley wrote:
             | Yeah this seems silly. You can do the same thing in git
             | (add and commit with the conflict still there)! Why you
             | would want to is a real mystery.
        
               | fweimer wrote:
               | It allows review of the way the merge conflict has been
               | resolved (assuming those changes a tracked and presented
               | in a useful way). This can be quite helpful when
               | backporting select fixes to older branches.
        
             | furyofantares wrote:
             | The conflict lines shown in the article are not present in
             | the file, they are a display of what has already been
             | merged. The merge had changes that were too near each other
             | and so the algorithm determined that someone needs to
             | review it, and the conflict lines are the result of
             | displaying the relevant history due to that determination.
             | 
             | In the example in the article, the inserted line from the
             | right change is floating because the function it was in
             | from the left has been deleted. That's the state of the
             | file, it has the line that has been inserted and it does
             | not have the lines that were deleted, it contains both
             | conflicting changes.
             | 
             | So in that example you indeed must resolve it if you want
             | your program to compile, because the changes together
             | produce something that does not function. But there is no
             | state about the conflict being stored in the file.
        
               | theK wrote:
               | Isnt that a bit dangerous in its own? If the merge
               | process can complete without conflicts being resolved,
               | doesnt it just push the Problem down the road? All of a
               | sudden you have to deal with failing CI or ghost features
               | that involve multiple people where actually you just
               | should has solved you conflict locally at merge time.
        
               | furyofantares wrote:
               | The tooling can force resolution at any step desired.
        
               | theK wrote:
               | What's the point of options when there only is one
               | correct answer?
        
               | furyofantares wrote:
               | The conflict is no longer an ephemeral part of the merge
               | that only ever lives as markup in the source files and is
               | stomped by the resolution that's picked, but instead a
               | part of history.
               | 
               | I think it is also not true that there's only one correct
               | answer, although I don't know how valuable this is.
               | 
               | For committing let's say yes, only one correct answer.
               | Say the tool doesn't let you commit after you've merged
               | without resolving conflicts.
               | 
               | But continuing to work locally you may want to put off
               | resolving the conflict temporarily. Like person A changed
               | the support email to help@example.com and person B
               | changed it to support@example.com - obviously some wires
               | go crossed and I will have to talk to A or B before
               | committing the merge and pushing, but I can also go ahead
               | and test the rest of the merge just fine.
               | 
               | And heck, maybe even committing after merging is fine but
               | pushing requires resolving. Then I can continue working
               | and committing locally on whatever else I was working on,
               | and I'll only resolve it if I need to push. Which may
               | mean I never need to resolve it, because A or B resolve
               | it and push first.
        
             | Someone wrote:
             | In this model, conflicts do not exist, so there are no
             | conflict markers (the UI may show markers, but they get
             | generated from what they call "the weave")
             | 
             | Because of that, I think it is worse than "but it is not
             | valid syntax"; it's "but it may not be valid syntax". A
             | merge may create a result that compiles but that neither of
             | the parties involved intended to write.
        
           | anentropic wrote:
           | If other systems are doing it too then I guess it must be
           | useful
           | 
           | But why is it useful to be able to defer conflict resolution?
           | 
           | I saw in a parallel comment thread people discussing merge
           | commit vs rebase workflow - rebase gives cleaner git history
           | but is a massive pain having to resolve conflicts on every
           | commit since current branch diverged instead of just once on
           | the final result with merge commit.
           | 
           | Is it that? Deferred conflict resolution allows you to rebase
           | but only resolve conflicts at the end?
        
             | tcoff91 wrote:
             | Deferred conflict resolution is amazing in jj because I may
             | never return to some of the branches that are in conflict
             | and therefore might never bother resolving them.
             | 
             | I rebase entire trees of commits onto main daily. I work on
             | top of a dev-base commit and it has all kinds of anonymous
             | branches off it. I rebase it and all its subbranches in 1
             | command and some of those sub branches might now be in a
             | conflicted state. I don't have to resolve them until I need
             | to actually use those commits.
             | 
             | dev-base is an octopus merge of in-flight PRs of mine. When
             | work is ready to be submitted it moves from being a
             | descendent of dev-base to a parent of dev-base.
             | 
             | Rebasing all my PRs and dev-base and all its descendents is
             | 1 command. Just make sure my @ is a descendent of dev-base
             | and then run: jj rebase -d main
        
         | h14h wrote:
         | Probably depends on what is in the merge. Lately I've been
         | collaborating a ton on PRDs and software specs in markdown (now
         | that agents have gotten pretty good at turning it into usable
         | code) and using git had been pretty painful. Especially when
         | working with a domain expert whose not as technical, git is
         | proving to almost be more of a barrier than an aid.
         | 
         | For this kind of work (which I suspect will only get more
         | common), a CRDT-based VCS makes a lot of sense.
        
         | gitmwnkdkc wrote:
         | Yes and no. Most often conflicts could have been handled
         | automatically with better tools. For example I have a script
         | that makes a copy of the whole folder and tries to merge each
         | commit using all of git's different merge stategies, and all
         | sub stategies, and presents which ones can merge without any
         | conflicts. It has been mind opening. Why git doesn't have this
         | built-in I don't understand.
         | 
         | Git also writes (non-logs) to the .git folder for operations
         | that you would assume should have been r/o, but that's another
         | problem (that affects things later on).
        
         | Levitating wrote:
         | > Conflicts are informative, not blocking. ... Conflicts are
         | surfaced for review when concurrent edits happen "too near"
         | each other, but they never block the merge itself.
         | 
         | So conflicts are still surfaced for review.
        
       | simonw wrote:
       | This thing is really short.
       | https://github.com/bramcohen/manyana/blob/main/manyana.py is 473
       | lines of dependency-free Python (that file only imports difflib,
       | itertools and inspect) and of that ~240 lines are implementation
       | and the rest are tests.
        
         | zahlman wrote:
         | It's really impressive what can be done in a few hundred lines
         | of well-thought-out Python without resorting to brutal hacks.
         | People complain about left-pad incidents etc. in the JS world
         | but I honestly feel like the Python ecosystem could do with
         | more, smaller packages on balance. They just have to be put
         | forward by responsible people who aren't trying to make a point
         | or inflate artificial metrics.
        
           | josephg wrote:
           | I bet you can make a small, beautiful implementation of this
           | algorithm in most languages. Most algorithms - even ones that
           | take generations of researchers to figure out - end up tiny
           | in practice if you put the work in to understand them
           | properly and program them in a beautiful way. Transformers
           | are the same. Genius idea. But a very small amount of code to
           | implement.
           | 
           | This is an implementation of FugueMax (Weidner and Kleppmann)
           | done using a bunch of tricks from Yjs (Jahns). There's
           | generations of ideas here, by lots of incredibly smart
           | people. And it turns out you can code the whole thing up in
           | 250 lines of readable typescript. Again with no dependencies.
           | 
           | https://github.com/josephg/crdt-from-
           | scratch/blob/master/crd...
        
             | zahlman wrote:
             | I'm not familiar with CRDT but the code does look pretty
             | nice. I actually have been thinking myself of streaming my
             | development, but just the terminal without camera or
             | microphone. (So I think I want to wait until I'm doing
             | something that will look pretty in the terminal.)
        
         | sayrer wrote:
         | The joke is there in the name. It is wrong (on purpose): it
         | should be "Manana". That term means "tomorrow" in your Spanish
         | class, but it can mean "later/future/morning" or even "later
         | this afternoon".
         | 
         | In English, you might think of "procrastination" or "we'll get
         | to it."
         | 
         | In Portuguese, you would say "proxima semana", literally "next
         | week", but it means "we'll get to it" (won't get to it).
        
       | mikey-k wrote:
       | Interesting idea. While conflicts can be improved, I personally
       | don't see it as a critical challenge with VCS.
       | 
       | What I do think is the critical challenge (particularly with Git)
       | is scalability.
       | 
       | Size of repository & rate of change of repositories are starting
       | to push limits of git, and I think this needs revisited across
       | the server, client & wire protocols.
       | 
       | What exactly, I don't know. :). But I do know that in my current
       | role (mid-size well-known tech company) is hitting these limits
       | today.
        
         | layer8 wrote:
         | One solution is to decompose your code into modules with stable
         | interfaces and reference them as versioned dependencies.
        
         | procaryote wrote:
         | What kind of scalability issues have you had with git?
         | 
         | Is it because of a monorepo?
        
           | mikey-k wrote:
           | yes - monorepo. Git (and associated service providers) have a
           | lot of work to do to scale out to large organizations working
           | in a single code base.
           | 
           | "Better Merge Conflicts" is not on this list.
           | 
           | Although I'm sympathetic to the problem, and I've personally
           | worked on "Merge Conflicts at Scale". Some of what's being
           | suggested here is interesting. I question if it makes a
           | material difference in the "age of ai", where an AI can
           | probably go figure out enough context to "figure things out".
        
             | adastra22 wrote:
             | Merge conflict avoidance is not a monorepo issue. In fact,
             | the whole purpose of a monorepo is to avoid these sorts of
             | issues, so it's not surprising.
             | 
             | Merge conflict hell shows up when, for example, you
             | maintain a long-lived feature branch periodically rebased
             | against an indifferent upstream that has its own
             | development priorities.
             | 
             | I've maintained a project for years that was in this sort
             | of situation. About ~100 commits on top of upstream, but
             | invasive ones that touched nearly every file. Every six
             | months upstream did a new tagged release. It would take me
             | literally _weeks_ of effort to rebase our patches on top,
             | as nearly every commit triggered its own merge conflict
             | hell.
             | 
             | You don't encounter these sorts of issues in a monorepo.
        
       | lifeformed wrote:
       | My issue with git is handling non-text files, which is a common
       | issue with game development. git-lfs is okay but it has some
       | tricky quirks, and you end up with lots of bloat, and you can't
       | merge. I don't really have an answer to how to improve it, but it
       | would be nice if there was some innovation in that area too.
        
         | miloignis wrote:
         | I really think something like Xet is a better idea to augment
         | Git than LFS, though it seems to pretty much only be used by
         | HuggingFace for ML model storage, and I think their git plugin
         | was deprecated? Too bad if it ends up only serving the
         | HuggingFace niche.
        
         | rectang wrote:
         | Has there ever been a consideration for the git file format to
         | allow storage of binary blobs uncompressed?
         | 
         | When I was screwing around with the Git file format, tricks I
         | would use to save space like hard-linking or memory-mapping
         | couldn't work, because data is always stored compressed after a
         | header.
         | 
         | A general copy-on-write approach to save checkout space is
         | presumably impossible, but I wonder what other people have
         | traveled down similar paths have concluded.
        
         | zahlman wrote:
         | What strategies would you like to use to diff the binaries? Or
         | else how are you going to avoid bloat?
         | 
         | Is it actually okay to try to merge changes to binaries? If two
         | people modify, say, different regions of an image file (even in
         | PNG or another lossless compression format), the sum of the
         | visual changes isn't necessarily equal to the sum of the byte-
         | level changes.
        
           | jayd16 wrote:
           | The best solution I've seen is prevention.
           | 
           | What you can do in P4 is work in trunk, make sure you have
           | latest and lock binary files you're working on. If you do
           | that you won't have conflicts (at the file level anyway).
           | Unlike git's design, this collaborative model is centralized
           | and synchronous but it works.
           | 
           | Git is missing the built in binary support, the locking, and
           | the efficient information sharing of file status tracking.
           | With LFS you can cobble something together but it's not fast
           | or easy.
           | 
           | I'm all for other solutions but I wish git would at least
           | support this flow more whole heartedly until something else
           | is invented.
        
         | jayd16 wrote:
         | Totally agree. After trying to flesh out Unreal's git plugin,
         | it really shows how far from ideal git really is.
         | 
         | Partial checkouts are awkward at best, LFS locks are somehow
         | still buggy and the CLI doesn't support batched updates.
         | Checking the status of a remote branch vs your local (to
         | prevent conflicts) is at best a naive polling.
         | 
         | Better rebase would be a nice to have but there's still so much
         | left to improve for trunk based dev.
        
         | gregschoeninger wrote:
         | We're working on this project to help with the non-text file
         | and large file problem: https://github.com/Oxen-AI/Oxen
         | 
         | Started with the machine learning use case for datasets and
         | model weights but seeing a lot of traction in gaming as well.
         | 
         | Always open for feedback and ideas to improve if you want to
         | take it for a spin!
        
         | samuelstros wrote:
         | Improving on "git not handling non-text files" is a semantic
         | understanding aka parse step in between the file write.
         | 
         | Take a docx, write the file, parse it into entities e.g.
         | paragraph, table, etc. and track changes on those entities
         | instead of the binary blob. You can apply the same logic to
         | files used in game development.
         | 
         | The hard part is making this fast enough. But I am working on
         | this with lix [0].
         | 
         | [0] https://github.com/opral/lix
        
           | jayd16 wrote:
           | What's the plan for large files that can't be merged? Images,
           | executable binaries, encrypted files, that sort of thing?
        
             | samuelstros wrote:
             | Simple left or right merge. One overwrites the other one.
             | 
             | The appeal or structured file formats like .docx, .json,
             | etc. Images are unstructured and simple "do you want to
             | keep the left or right image" is good enough.
        
       | gnarlouse wrote:
       | I think something like this needs to be born out of analysis of
       | gradations of scales of teams using version control systems.
       | 
       | - What kind of problems do 1 person, 10 person, 100 person, 1k
       | (etc) teams really run into with managing merge conflicts?
       | 
       | - What do teams of 1, 10, 100, 1k, etc care the most about?
       | 
       | - How does the modern "agent explosion" potentially affect this?
       | 
       | For example, my experience working in the 1-100 regime tells me
       | that, for the most part, _the kind of merge conflict_ being
       | presented here is resolved by assigning subtrees of code to
       | specific teams. For the large part, merge conflicts don 't
       | happen, because teams coordinate (in sprints) to make orthogonal
       | changes, and long-running stale branches are discouraged.
       | 
       | However, if we start to mix in agents, a 100 person team could
       | quickly jump into a 1000 person team, esp if each person is using
       | subagents making micro commits.
       | 
       | It's an interesting idea definitely, but without real-world data,
       | it kind of feels like this is just delivering a solution without
       | a clear problem to assign it to. Like, yes merge-conflicts are a
       | bummer, but they happen infrequently enough that it doesn't break
       | your heart.
        
         | CuriouslyC wrote:
         | Team scale doesn't tend to impact this that much, since as
         | teams grow they naturally specialize in parts of the codebase.
         | Shared libs can be hotspots, I've heard horror stories at large
         | orgs about this sort of thing, though usually those shared libs
         | have strong gatekeeping that makes the problem more one of
         | functionality living where it shouldn't to avoid gatekeeping
         | than a shared lib blowing up due to bad change set merges.
        
         | tasuki wrote:
         | > What kind of problems do 1 person, 10 person, 100 person, 1k
         | (etc) teams really run into with managing merge conflicts?
         | 
         | > What do teams of 1, 10, 100, 1k, etc care the most about?
         | 
         | Oh god no! That would be about the worst way to do it.
         | 
         | Just make it conceptually sound.
        
           | gnarlouse wrote:
           | Probably, but just introducing CRDTs also feels like the
           | wrong way to approach the problem! :)
        
           | meindnoch wrote:
           | Also, we need _personas_! Sally the developer, Mark the UX
           | designer, Taylor the manager. Also, we need to build a
           | _community_ , with the help of evangelists!
        
         | jillesvangurp wrote:
         | > How does the modern "agent explosion" potentially affect
         | this?
         | 
         | This changes everything. Agents don't really care what
         | versioning software is used. They can probably figure out
         | whatever you are using. But they'll likely assume it's
         | something standard (i.e. Git) so the easiest is to not get too
         | adventurous. Also, the reasons to use something else mostly
         | boil down to user friendliness and new merge strategies.
         | However, lately I just tell codex to pull and deal with merge
         | conflicts. It's not something I have to do manually anymore.
         | That removes a key reason for me to be experimenting with
         | alternative version control systems. It's not that big of a
         | problem anymore.
         | 
         | Git was actually designed for massive teams (the Linux kernel)
         | but you have to be a bit disciplined using it in a way that
         | many users in smaller teams just aren't. With agentic coding
         | tools, you can just codify what you want to happen in
         | guardrails and skills. Including how to deal with version
         | control and what process to follow.
         | 
         | Where more advanced merge strategies could be helpful is the
         | type of large scale refactoring that are now much easier with
         | agentic coding tools. But doing that in repositories with lots
         | of developers working on other changes is not something that
         | should happen very often. And certainly not without a lot of
         | planning and coordination probably.
        
           | lcbasu wrote:
           | >Agents don't really care what versioning software is used
           | 
           | Strongly agree that agents don't care about the VCS as they
           | will figure out whatever you throw at them. And you are right
           | about that the merge conflicts are becoming a solved problem
           | when you can just tell an agent to handle it.
           | 
           | But I think there is a much bigger problem emerging that
           | better merge strategies (CRDT or otherwise) do not even
           | touch: the reasoning is gone.
           | 
           | For example the situation taken from the blog is that one
           | side deletes a function while another adds a logging line
           | inside it. The CRDT will give you a better conflict display
           | showing what each side did. Great. But it still doesn't tell
           | you why the function was deleted. Was it deprecated? Moved?
           | Replaced by something else? The reviewer is still reverse-
           | engineering intent from the diff.
           | 
           | This gets/will get much worse with coding agents as agentic
           | commits are orders of magnitude larger, and the commit
           | message barely summarises what happened. An agent might
           | explore three approaches, hit dead ends, flag something as
           | risky, then settle on a solution. All that context vanishes
           | after the session ends.
           | 
           | You are right about codifying guardrails and skills, and I
           | think that is the more productive direction compared to
           | replacing git. We should augment the workflow around it. I
           | also started from a much more radical place, actually,
           | thinking we need to ditch git entirely for agentic workflows
           | [1]. BUT the more I built with agents, the more I realized
           | the pragmatic first step is just preserving the reasoning
           | trail alongside the code, right there in git[2]. No new VCS
           | needed, and the next agent or human that touches the code has
           | the full "WHY" available.
           | 
           | [1] https://github.com/lcbasu/git4aiagents/commit/3a3b197#dif
           | f-b... [2]https://www.git4aiagents.com
        
       | jFriedensreich wrote:
       | starts with "based on the fundamentally sound approach of using
       | CRDTs for version control". How on earth is crdt a sound base for
       | a version control system? This makes no sense fundamentally, you
       | need to reach a consistent state that is what you intended not
       | what some crdt decided and jj shows you can do that also without
       | blocking on merges but with first level conflicts that need to be
       | resolved. ai and language aware merge drivers are helping so much
       | here i really wonder if the world these "replace version control"
       | projects were made for still exists at all.
        
         | miloignis wrote:
         | The rest of the article shows exactly how a CRDT is a sound
         | base for a version control system, with "conflicts" and all.
        
           | skydhash wrote:
           | But the presentation does not show how it resolves conflicts.
           | For the first example, Git has the 3 way-merge that shows the
           | same kind of info. And a conflict is not only to show that
           | two people have worked on a file. More often than not, it
           | highlight a semantic changes that happened differently in two
           | instances and it's a nice signal to pay attention to this
           | area. But a lot of people takes merge conflicts as some kind
           | of nuisance that prevents them from doing their job (more
           | often due to the opinion that their version is the only good
           | one).
        
           | jFriedensreich wrote:
           | where?
        
         | nozzlegear wrote:
         | > _ai and language aware merge drivers are helping so much here
         | i really wonder if the world these "replace version control"
         | projects were made for still exists at all._
         | 
         | I really wonder what kinds of magical AI you're using, because
         | in my experience, Claude Code chokes and chokes hard on complex
         | rebases/merge conflicts to the point that I couldn't trust it
         | anymore.
        
           | jFriedensreich wrote:
           | the latest codex or opus 4.6 depending what works better. the
           | trick is not to work on giant rebases at all. use commit
           | stacks that constantly rebase on trunk so will constantly
           | have small conflicts that are simple to resolve rather than
           | waiting for giant headaches. another one is to use jj and
           | resolve conflicts "through the stack" so you rebase your work
           | stack, then resolve conflicts from the bottom commit up, one
           | by one, not all at once.
        
       | jauntywundrkind wrote:
       | In case the name doesn't jump out at you, this is Bram Cohen,
       | inventory of Bittorrent. And Chia proof-of-storage (probably
       | better descriptions available) cryptocurrency.
       | https://en.wikipedia.org/wiki/Bram_Cohen
       | 
       | It's not the same as capturing it, but I would also note that
       | there are a wide _wide_ variety of ways to get 3-way merges  / 3
       | way diffs from git too. One semi-recent submission (2022
       | discussing a 2017) discussed diff3 and has some excellent
       | comments (https://news.ycombinator.com/item?id=31075608),
       | including a _fantastic_ incredibly wide ranging round up of merge
       | tools (https://www.eseth.org/2020/mergetools.html).
       | 
       | However/alas git 2.35's (2022) _fabulous_ zdiff3 doesn 't seems
       | to have any big discussions. Other links welcome but perhaps
       | https://neg4n.dev/blog/understanding-zealous-diff3-style-git...?
       | It works excellently for me; enthusiastically recommended!
        
       | ulrikrasmussen wrote:
       | The thing about how merges are presented seems orthogonal to how
       | to represent history. I also hate the default in git, but that is
       | why I just use p4merge as a merge tool and get a proper 4-pane
       | merge tool (left, right, common base, merged result) which shows
       | everything needed to figure out why there is a conflict and how
       | to resolve it. I don't understand why you need to switch out the
       | VCS to fix that issue.
        
         | crote wrote:
         | Seconding the use of p4merge for easy-to-use three-pane
         | merging. Just like most other issues with Git, if your merges
         | are painful it's probably due to terrible native UX design -
         | not due to anything _conceptually_ wrong with Git.
        
           | TacticalCoder wrote:
           | Thirding it except I do it from Emacs. Three side-by-side
           | pane with left / common ancestor / right and then below the
           | merge result. By default it's not like that but then it's
           | Emacs so anything is doable. I hacked some elisp code a great
           | many years ago and I've been using it ever since.
           | 
           | No matter the tool, merges should _always_ be presented like
           | that. It 's the only presentation that makes sense.
        
             | MarsIronPI wrote:
             | What tool do you use? Does Magit support it natively?
        
               | skydhash wrote:
               | I think you need to enable 3 way merge by default in
               | git's configuration, and both smerge (minor mode for
               | solving conflicts) and ediff (major mode that encompass
               | diff and patch) will pick it up. In the case of the
               | latter you will have 4 panes, one for version A, another
               | for version B, a third for the result C, and the last is
               | the common ancestor of A and B.
               | 
               | Addendum: I've since long disabled it. A and B changes
               | are enough for me, especially as I rebase instead of
               | merging.
        
             | jwr wrote:
             | Isn't that what ediff does?
        
             | arikrahman wrote:
             | The extensibility provided with Emacs Lisp has been helpful
             | for hacking together my own Git/Jujutsu plugin. I tried to
             | model it over lazygit/lazyjj although magit has been
             | incredible to use and hard to depart from.
        
           | roryokane wrote:
           | Did you know that VS Code added support for the same four-
           | pane view as p4merge years ago? I used p4merge as my merge
           | tool for a long time, but I switched to VS Code when I
           | discovered that, as VS Code's syntax highlighting and text
           | editing features are much better than p4merge's.
           | 
           | I also use the merge tool of JetBrains IDEs such as IntelliJ
           | IDEA (https://www.jetbrains.com/help/idea/resolve-
           | conflicts.html#r...) when working in those IDEs. It uses a
           | three-pane view, not a four-pane view, but there is a menu
           | that allows you to easily open a comparison between any two
           | of the four versions of the file in a new window, so I find
           | it similarly efficient.
        
             | stbtrax wrote:
             | how do you set that up? the default git tool version seems
             | to be 3 pane
        
               | ramchip wrote:
               | Looks like it's "Show Base" under the top-level "..."
               | menu when working on a merge conflict
               | 
               | https://github.com/microsoft/vscode/issues/155277#issueco
               | mme...
        
         | roryokane wrote:
         | Even if you don't use p4merge, you can set Git's
         | merge.conflictStyle config to "diff3" or "zdiff3" (https://git-
         | scm.com/docs/git-config#Documentation/git-config...). If you do
         | that, Git's conflict markers show the base version as well:
         | <<<<<<< left       ||||||| base       def calculate(x):
         | a = x * 2           b = a + 1           return b       =======
         | def calculate(x):           a = x * 2
         | logger.debug(f"a={a}")           b = a + 1           return b
         | >>>>>>> right
         | 
         | With this configuration, a developer reading the raw conflict
         | markers could infer the same information provided by Manyana's
         | conflict markers: that the right side added the logging line.
        
           | ktm5j wrote:
           | I'm on my phone right now so I'm not going to dig too hard
           | for this, but you can also configure a "merge tool" (or
           | something like that) so you can use Meld or Kompare to make
           | the process easier. This has helped me in a pinch to work out
           | some confusing merge conflicts.
        
             | newsoftheday wrote:
             | I started using Meld years ago and continue to find people
             | who've never heard of it. It's a pretty good tool.
        
             | otherayden wrote:
             | Huge meld fan here, recommended by a professor about a year
             | ago. Game changer
        
           | psychoslave wrote:
           | That still have an issue with the vocabulary. Things like
           | "theirs/our" is still out of touch but it's already better
           | than a loose spatial analogy on some representation of the
           | DAG.
           | 
           | Something like base, that is "common base", looks far more
           | apt to my mind. In the same vein, endogenous/exogenous would
           | be far more precise, or at least aligned with the concern at
           | stake. Maybe "local/alien" might be a less pompous vocabulary
           | to convey the same idea.
        
             | kungito wrote:
             | After 15 years i still cant remember which is which. I get
             | annoyed every time. Maybe I should invest 15 minutes
             | finally to remember properly
        
               | IgorPartola wrote:
               | Let's see if I get this wrong after 25 years of git:
               | 
               | ours means what is in my local codebase.
               | 
               | theirs means what is being merged into my local codebase.
               | 
               | I find it best to avoid merge conflicts than to try to
               | resolve them. Strategies that keep branches short lived
               | and frequently merging main into them helps a lot.
        
               | marcellus23 wrote:
               | That's kind of the simplest case, though, where "theirs"
               | and "ours" makes obvious sense.
               | 
               | What if I'm rebasing a branch onto another? Is "ours" the
               | branch being rebased, or the other one? Or if I'm
               | applying a stash?
        
               | IgorPartola wrote:
               | > What if I'm rebasing a branch onto another?
               | 
               | Just checkout the branch you are merging/rebasing into
               | before doing it.
               | 
               | > Or if I'm applying a stash?
               | 
               | The stash is in that case effectively a remote branch you
               | are merging into your local codebase. ours is your local,
               | theirs is the stash.
        
               | sheept wrote:
               | "Ours" and "theirs" make sense in most cases (since
               | "ours" refers to the HEAD you're merging into).
               | 
               | Rebases are the sole exception (in typical use) because
               | ours/theirs is reversed, since you're merging HEAD into
               | the other branch. Personally, I prefer merge commits over
               | rebases if possible; they make PRs harder for others to
               | review by breaking the "see changes since last review"
               | feature. Git generally works better without rebases and
               | squash commits.
        
               | sebmellen wrote:
               | Wow, interesting to see such a diametrically opposed
               | view. We've banned merge commits internally and our
               | entire workflow is rebase driven. Generally, I find that
               | rebases are far better at keeping Git history clean and
               | clearly allowing you to see the diff between the base
               | you're merging into and the changes you've made.
        
               | Ajedi32 wrote:
               | Yes, I prefer that approach as well because it allows the
               | person who authored the change to do all the work of
               | deciding how to resolve conflicts up front (and allows
               | reviewers to review that conflict resolution) instead of
               | forcing whoever eventually does the merge to figure
               | everything out after the fact. It also removes conflicts
               | from the history so you never have to think about them
               | later after the rebase/merge process is finished.
        
               | KPGv2 wrote:
               | > Git generally works better without rebases and squash
               | commits.
               | 
               | If squash commits make Git harder for you, that's a tell
               | that your branches are trying to do too many things
               | before merging back into main.
        
               | ralferoo wrote:
               | I don't know. Even when I'm working on my own private
               | repositories across several machines, I really, really
               | dislike regular merges. You get an ugly commit message
               | and I can never get git log to show me the information I
               | actually want to see.
               | 
               | For me, rebasing is the simplest and easiest to
               | understand, and it allows you to squash some of your
               | commits so that it's one commit per feature / bug-fix /
               | logical unit of work. I'll also frequently rebase and
               | squash commits in my work branch too, where I've
               | temporarily committed something and then fixed a bug
               | before it's been pushed into main, I'll just reorder and
               | squash the relevant commits into one.
        
               | andy_ppp wrote:
               | I completely agree, since doing rebase our history looks
               | fantastic and it makes finding things, cherrypicking and
               | generating changelogs really simple. Why not be neat,
               | it's cost us nothing and you can make yourself a tutorial
               | on Claude if you don't understand rebasing pretty easily.
        
               | andy_ppp wrote:
               | Don't do squash commits, just rebase -i your branch
               | before merging so you only have one commit. It's pretty
               | trivial to do.
        
               | em-bee wrote:
               | a better (more confusing) example:
               | 
               | i have a branch and i want to merge that branch into
               | main.
               | 
               | is ours the branch and main theirs? or is ours main, and
               | the branch theirs?
        
               | IgorPartola wrote:
               | I always checkout the branch I am merging something into.
               | I was vaguely aware I could have main checked out but
               | merge foo into bar but have never once done that.
        
               | Sharlin wrote:
               | git checkout mybranch       git rebase main
               | 
               | A conflict happens. Now "ours" is _main_ and  "theirs" is
               | _mybranch_ , even though from your perspective you're
               | still on mybranch. Git isn't, however.
        
               | IgorPartola wrote:
               | Ah that's fair. This is why I would do a `git merge main`
               | instead of a rebase here.
        
               | ljm wrote:
               | I have met more than one person who would doggedly
               | tolerate rebase, not even using rerere, instead of doing
               | a simple 'git merge --no-ff' to one-shot it, not
               | understanding that rebase touches every commit in the
               | diff between main and not simply the latest change on
               | HEAD.
               | 
               | Not a problem if you are a purist on linear history.
        
               | em-bee wrote:
               | _not understanding that rebase touches every commit in
               | the diff_
               | 
               | it sounds like that's a problem for you. why would that
               | be? i prefer rebase and fast forward, but i am fully
               | aware that rebase rewrites all commits.
        
               | clktmr wrote:
               | The thing is, you'll typically switch to master to merge
               | your own branch. This makes your own branch 'theirs',
               | which is where the confusion comes from.
        
               | IgorPartola wrote:
               | Not me. I typically merge main onto a feature branch
               | where all the conflicts are resolved in a sane way. Then
               | I checkout main and merge the feature branch into it with
               | no conflicts.
               | 
               | As a bonus I can then also merge the feature branch into
               | main as a squash commit, ditching the history of a
               | feature branch for one large commit that implements the
               | feature. There is no point in having half implemented
               | and/or buggy commits from the feature branch clogging up
               | my main history. Nobody should ever need to revert main
               | to that state and if I really really need to look at that
               | particular code commit I can still find it in the feature
               | branch history.
        
               | throwaway7783 wrote:
               | Yep. This is the only model that has worked well for me
               | for more than a decade.
        
               | KPGv2 wrote:
               | This is what I do, and I was taught by an experienced Git
               | user over a decade ago. I've been doing it ever since.
               | All my merges into main are fast forwards.
        
               | KPGv2 wrote:
               | > ours means what is in my local codebase
               | 
               | Since it's always one person doing a merge, why isn't it
               | "mine" instead of "ours"? There aren't five of us at my
               | computer collaboratively merging in a PR. There is one
               | person doing it.
               | 
               | "Ours" makes it sound like some branch everyone who's
               | working on the repo already has access to, not the active
               | branch on _my_ machine.
        
               | itintheory wrote:
               | That's between you and git.
        
               | imiric wrote:
               | > Let's see if I get this wrong after 25 years of git
               | 
               | You used it 5 years before Linus? Impressive!
        
               | IgorPartola wrote:
               | Haha yes. You caught me :)
               | 
               | I was wondering when someone was going to point it out. I
               | actually have only been using it since about 2009 after a
               | brief flirtation with SVN and a horrible breakup with
               | CVS.
        
               | afiori wrote:
               | iirc ours is always the commit the merge is starting
               | from. the issue is that with a merge your current commit
               | is the merging commit while with a rebase it is reversed.
               | 
               | I suspect that this could be because the rebase command
               | is implemented as a serie of merges/cherry-picks from the
               | target branch.
        
               | Sharlin wrote:
               | git checkout mybranch       git rebase main
               | 
               | Now git takes main and starts cloning (cherry-picking, as
               | you said) commits from mybranch on top of it. From git's
               | viewpoint it's working on top of main, so if a conflict
               | occurs, main is "ours" and mybranch is "theirs". But from
               | your viewpoint you're still on mybranch, and indeed are
               | left on mybranch when the rebase is complete. (It's a
               | _different_ mybranch, of course; once the rebase is
               | completed, git moves mybranch to point to the new
               | (detached) HEAD.) Which makes  "ours" and "theirs"
               | exactly the opposite of what the user expects.
        
               | XorNot wrote:
               | Man do I hate this behavior because it would be really
               | some by just using the branch names rather then "ours"
               | and "theirs"
        
               | Sharlin wrote:
               | Agreed. Even when the branch is the same, it would always
               | be distinguishable by <remote-name>/<branch-name> vs.
               | just <branch-name>.
        
               | orthoxerox wrote:
               | I had to make an alias for rebasing, because I kept doing
               | the opposite:                   git checkout master
               | #check out the branch to apply commits to         git
               | rebase mybranch #Apply all commits from mybranch
               | 
               | Now I just write                   rebase-current-branch
               | 
               | and it does what I want: fetches origin/master and
               | rebases my working branch on top of it.
               | 
               | But "ours"/"theirs" still keeps tripping me up.
        
               | cerved wrote:
               | Tip, you may want to use origin/HEAD over origin/master
        
               | orthoxerox wrote:
               | Is it the naming-independent identifier of the tip of the
               | trunk?
        
               | skydhash wrote:
               | You can use the --onto flag for git rebase
               | git rebase --onto origin/master
               | 
               | It will checkout origin/master and replay the current
               | branch on top.
               | 
               | P.S. I had to check the man page as I use Magit. In the
               | latter I tap r, then u. In magit my upstream is usually
               | the main trunk. You can also tap e instead of u to choose
               | the base branch.
        
               | awesome_dude wrote:
               | This is one of my pain points, and one time I googled and
               | got the real answer (which is why it's such a pain
               | point).
               | 
               | That answer is "It depends on the context"
               | 
               | > The reason the "ours" and "theirs" notions get swapped
               | around during rebase is that rebase works by doing a
               | series of cherry-picks, into an anonymous branch
               | (detached HEAD mode). The target branch is the anonymous
               | branch, and the merge-from branch is your original (pre-
               | rebase) branch: so "--ours" means the anonymous one
               | rebase is building while "--theirs" means "our branch
               | being rebased".[0]
               | 
               | [0] https://stackoverflow.com/questions/25576415/what-is-
               | the-pre...
        
               | flutetornado wrote:
               | I ended up creating a personal vim plugin for merges one
               | night because of a frustrating merge experience and never
               | being able to remember what is what. It presents just two
               | diff panes at top to reduce the cognitive load and a
               | navigation list in a third split below to switch between
               | diffs or final buffer (local/remote, base/local,
               | base/remote and final). The list has branch names next to
               | local/remote so you always know what is what. And most of
               | the time the local/remote diff is what I am interested in
               | so that's what it shows first.
        
               | mamcx wrote:
               | Seriously!
               | 
               | Why not show the names of the branch + short Id (and when
               | is not direct name, at least "this is from NAME")
        
               | sheept wrote:
               | doesn't it? Next to the conflict markers, it'll display
               | HEAD, the ref name, or the short commit hash.
        
               | cerved wrote:
               | It does
        
               | KPGv2 wrote:
               | I'll be honest, as a fairly skilled and experienced
               | programmer who isn't a git expert, I know what HEAD
               | means, but when I'm rebasing I really have no idea. It
               | all seems to work out in the end because my collaborative
               | work is simple and usually 2-3 people only, so I'm never
               | rebasing against a ton of commits I lack context for
               | (because 90% of them are _my_ commits since I 'm usually
               | dealing with PRs to my open source projects rather than
               | someone else's).
               | 
               | HEAD is "the thing we're editing now" but that's not
               | terribly useful when rebasing since you're repeatedly
               | editing a fake history.
        
               | lmm wrote:
               | I avoid this problem by not rebasing.
        
               | jimbobimbo wrote:
               | Seriously! I have too many years of software development
               | experience, but I use Visual Studio UX to handle pretty
               | much all git operations. And always merge.
               | 
               | I have better things to do in my life than
               | "internalizing" anything that doesn't matter in the grand
               | scheme of things.
        
               | ozim wrote:
               | I don't like that approach, because people who work like
               | that commit all kind of crap to repo or cry that GIT ate
               | their homework...
               | 
               | Then we have line ending conflicts, file format conflict
               | UTF8-BOM mixes with just UTF8 it makes more work for
               | everyone like crappy PRs. Because of people for who those
               | are things that ,,don't matter in grand scheme of
               | things".
        
               | eru wrote:
               | I happen to know a lot about git internals, but I don't
               | think everyone should need to.
               | 
               | About the line ending conflicts: set up your CI once to
               | complain about those. And help your coworkers set up
               | their editors right once.
        
               | gitmwnkdkc wrote:
               | If it hurts, do it more often.
        
               | ozim wrote:
               | Hey not every rebase has conflicts. I definitely rebase
               | when there are no conflicts, then merge.
               | 
               | When there are conflicts I merge ,,theirs" into my branch
               | to resolve those so I keep mental model for this side and
               | don't have to switch. Then rebase then open PR.
        
               | lmm wrote:
               | You could do all that. Or you could just merge every
               | time. I know which I find easier.
        
               | eru wrote:
               | I do the following to keep my sanity when doing something
               | like rebasing a feature branch onto latest origin/master:
               | 
               | * First and most important: turn on rerere.
               | 
               | * Second: merge and resolve all conflicts, commit.
               | 
               | * Third: rebase.
               | 
               | The second step might look redundant, but thanks to
               | rerere git remembers the merge conflict resolution. That
               | makes step 3 have fewer conflicts; and step 2 tends to be
               | easier on me, because we are only reconciling the final
               | outcomes.
               | 
               | (Well, I'm lying: the above is what I used to do.
               | Nowadays I let Claude handle that, and only intervene
               | when it gets too complicated for the bot.)
        
               | gwerbin wrote:
               | Git leaks a lot of implementation details into its UX.
               | Rebasing is meant to be equivalent to checking out the
               | "base" branch and cherry picking commits onto it.
               | Therefore "ours" during a rebase is the base branch.
               | 
               | The meaning of "ours" and "theirs" is always the same,
               | but the "base" of the operation is reversed compared to
               | what you might be used to during merge.
               | 
               | Rebasing can be confusing and hard and messy, but once I
               | learned that rule and took the time to internalize it, I
               | at least never got confused on this particular detail
               | again.
               | 
               | > fake history
               | 
               | That's the thing, it's not actually fake history. Git
               | really is doing the things it looks like it's doing
               | during a rebase. That's why you can do all kinds of weird
               | tricks like stopping in the middle to reset back a commit
               | in order to make a new intervening commit. The reason you
               | can abort at any time with (almost) no risk is because
               | the old history is still hanging around in the database
               | and won't be removed until GC runs, usually long after
               | the rebase is settled.
        
               | skydhash wrote:
               | Also git store (almost?) all its operations in the
               | reflog. They have identifier like commits so you can
               | reset to them and restore the original state of the
               | working directory (mostly after an automatic rebase gone
               | wrong).
        
               | gwerbin wrote:
               | That's the thing, they're not "like commits", they are
               | the actual original commits. It's a history of where the
               | HEAD ref used to be. Eventually those commits will be
               | pruned out of the tree if/when the reflog expires because
               | there is nothing left pointing to them. But otherwise
               | they are normal commits.
        
               | eru wrote:
               | I think what the grandfather comment meant is 'like' in
               | the sense of 'this is an example'. Not 'like' in the
               | sense of 'sorta / approximately'.
        
               | eru wrote:
               | Yes, Git is like a Copy-on-Write filesystem.
               | 
               | It's interesting that once even C programmers, like
               | Linus, become really experienced, they embrace the wisdom
               | that functional programmers are forced to swallow anyway.
        
               | PunchyHamster wrote:
               | Learning git properly is pretty much "read Git book at
               | least 3 times".
               | 
               | All of it makes sense and is decently intuitive once you
               | know how internals work.
               | 
               | People keep imagining git as a series of diffs while in
               | reality it's series of the filesystem tree snapshots + a
               | bunch of tools to manage that and reconcile changes in
               | face of merge. And most of that can be replaced if the
               | builtins are not up to task. And the experience is
               | getting slowly better but it's balance between power
               | users and newbies, and also trying to not break stuff
               | when going forward.
               | 
               | Now of course that sucks if programming is not someone's
               | day job but there is plenty of tools that present simpler
               | workflows built on top of that.
        
               | goku12 wrote:
               | > HEAD is "the thing we're editing now" but that's not
               | terribly useful when rebasing since you're repeatedly
               | editing a fake history.
               | 
               | You got two things wrong here. Firstly, HEAD isn't 'the
               | thing you're editing now'. HEAD is what you have already
               | committed. If you want to edit the HEAD, you have to
               | either amend the commit or reset and redo the commit. (To
               | make the situation even more complex, the amended or
               | overridden commit remains in the repo unchanged, but
               | orphaned.)
               | 
               | The actual thing being edited is a 'patch' that will
               | eventually be converted into a new commit (snapshot). If
               | you're doing a rebase and want to see the next patch in
               | the pipeline that you're editing now, try this:
               | git rebase --show-current-patch
               | 
               | Secondly, rebase is not editing a fake history. Rebase is
               | creating a new (and real) history by repeatedly cherry
               | picking commits from the old history based on the rebase
               | plan. HEAD is the tip commit of the new history under
               | construction. On completion of the rebase, the branch ref
               | of the old history is switched to the new history, where
               | HEAD is now at. Meanwhile, the old history remains in the
               | repo unchanged, but again orphaned.
               | 
               | All the orphaned commits are still visible in the HEAD's
               | reflog. You can use it to undo the rebase if you wish.
               | 
               | I agree that the entire thing is confusing as hell. But I
               | have a bunch of aliases and scripts that show you the
               | process graphically in realtime. You can use that
               | awareness to make the right call every time. I'm thinking
               | about converting it into a TUI application and publishing
               | it.
        
               | pcthrowaway wrote:
               | It does now by default, since v2.12 (released 2017).
               | Prior to that you had to set the log.decorate config.
               | Good times.
        
               | tome wrote:
               | It doesn't matter which is which. The resolution will be
               | the same regardless.
        
               | goku12 wrote:
               | I was thinking about creating a TUI application that
               | points out what each part in the conflict indicator
               | corresponds to. This idea is primarily meant for rebases
               | where the HEAD and the ID of the updated commits change
               | constantly. Think of it as a map view of the rebase
               | process, that improves your situational awareness by
               | presenting all the relevant information simultaneously.
               | That could trivially work for merges too.
        
             | wakawaka28 wrote:
             | >Maybe "local/alien" might be a less pompous vocabulary to
             | convey the same idea.
             | 
             | That is more alien and just as contrived. If you merge
             | branches that you made, they're both local and "ours". You
             | just have to remember that "ours" is the branch you are on,
             | and "theirs" is the other one. I have no idea what happens
             | in an octopus merge but anyway, the option exists to show
             | commit titles along with markers to help you keep it
             | straight.
        
               | psychoslave wrote:
               | Indeed, thanks.
               | 
               | Something that carry the meaning "the branch we want to
               | use as a starting point" and "the other branch we want to
               | integrate in the previous one" is what I had in mind, but
               | it might not fit all situations in git merge/rebase.
        
               | wakawaka28 wrote:
               | Assuming you have to start on one of the branches being
               | merged, "current" is a good name for the one you started
               | on. "Other" is good enough for the other one. By the way
               | I found out that octopus merges never succeed in case of
               | conflicts. I'm not even sure if prerecorded resolutions
               | work in that case. You're supposed to do a series of
               | normal merges instead if you have conflicts.
        
           | IshKebab wrote:
           | This is better but it still doesn't really help when the
           | conflict is 1000 lines and one side changed one character and
           | the other deleted the whole thing. That isn't theoretical -
           | it happens quite regularly.
           | 
           | What you really need is the ability to diff the base and
           | "ours" or "theirs". I've found most different UIs can't do
           | this. VSCode can, but it's difficult to get to.
           | 
           | I haven't tried p4merge though - if it can do that I'm sold!
        
             | pfg_ wrote:
             | I tried p4merge a while ago and it didn't do it
             | ubfortunately, still stuck copying the base and ours to
             | seperate files and diffing them.
        
               | IshKebab wrote:
               | So the way you can do it in VSCode is to open the
               | conflict in their smart merge editor... Often it is
               | actually smart enough to highlight the relevant change
               | but if not each of the left/right editors has a button in
               | its toolbar to diff it against the base.
               | 
               | Not the easiest to access but better than copying/pasting
               | (which is what I also used to do).
        
             | fransje26 wrote:
             | If I understood your point correctly, I believe that Meld
             | can do that. And then you get a windows as [1]. You can
             | configure git to choose which version goes where. Something
             | like:                   [mergetool "meld"]
             | cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"
             | #cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"
             | 
             | [1] https://linuxkamarada.com/files/2019/11/git-mergetool-
             | meld-e...
        
           | tempodox wrote:
           | I still find this shit unreadable, even after years of
           | practice.
        
             | warmwaffles wrote:
             | I've trained myself to avoid this entirely by avoiding
             | changing lines unnecessarily. With LLMs, I also force them
             | to stay concise and ONLY change what is absolutely
             | necessary.
        
         | cxr wrote:
         | > I don't understand why you need to switch out the VCS to fix
         | that issue.
         | 
         | For some reason, when it comes to this subject, most people
         | don't think about the problem as much as they think they've
         | thought about it.
         | 
         | I recently listened to an episode on a well-liked and respected
         | podcast featuring a guest there to talk about version control
         | systems--including their own new one they were there to promote
         | --and what factors make their industry different from other
         | subfields of software development, and why a new approach to
         | version control was needed. They came across as thoughtful but
         | exasperated with the status quo and brought up issues worthy of
         | consideration while mostly sticking to high-level claims. But
         | after something like a half hour or 45 minutes into the
         | episode, as they were preparing to descend from the high level
         | and get into the nitty gritty of their new VCS, they made an
         | offhand comment contrasting its abilities with Git's,
         | referencing Git's approach/design wrt how it "stores diffs"
         | between revisions of a file. I was bowled over.
         | 
         | For someone to be in that position and not have done even a
         | cursory amount of research before embarking on a months (years)
         | long project to design, implement, and then go on the talk
         | circuit to present their VCS really highlighted that the
         | familiar strain of NIH is still alive, even in the current era
         | where it's become a norm for people to be downright resistant
         | to writing a couple dozen lines of code themselves if there is
         | no existing package to import from NPM/Cargo/PyPI/whatever that
         | purports to solve the problem.
        
           | hn_throwaway_99 wrote:
           | > they made an offhand comment contrasting its abilities with
           | Git's, referencing Git's approach/design wrt how it "stores
           | diffs" between revisions of a file. I was bowled over.
           | 
           | It seems like you have taken offense to the phrase "stores
           | diffs", but I'm not sure why. I understand how commit
           | snapshots and packfiles work, and the way delta compression
           | works in packfiles might lead me to calling it "storing
           | diffs" in a colloquial setting.
        
             | ghusbands wrote:
             | A common misconception is that git works with diffs as a
             | primary representation of patches, and that's the implied
             | reading of "stores diffs". Yes, git uses diffs as an
             | optimisation for storage but the underlying model is always
             | that of storing whole trees (DAGs of trees, even), so
             | someone talking about it storing diffs is missing something
             | fundamental. Even renames are rederived regularly and not
             | stored as such.
             | 
             | However, context would matter and wasn't provided - without
             | it, we're just guessing.
        
             | cxr wrote:
             | > It seems like you have taken offense to the phrase
             | "stores diffs", but I'm not sure why.
             | 
             | Yeah, I'm not sure why it seems that way to you, either.
             | 
             | > the way delta compression works in packfiles might lead
             | me to calling it "storing diffs" in a colloquial setting
             | 
             | We're not discussing some fragment of some historical
             | artifact, one part of a larger manuscript that has been
             | lost or destroyed, with us left at best trying to guess
             | what they meant based on the little that we do have, which
             | amounts to nothing more than the words that you're focusing
             | on here.
             | 
             | Their remarks were situated within a context, and they went
             | on to speak for another hour and a half about the topic.
             | The fullness of that context--which was the basis of my
             | decision to comment--involved that person's very real and
             | very evident overriding familiarity with non-DVCS systems
             | that predate Git and that familiarity being treated as a
             | substitute for being knowledgeable about how Git itself
             | works when discussing it in a conversation about the
             | tradeoffs that different version control systems force you
             | to make.
        
         | galaxyLogic wrote:
         | Can it merge ordinary directories (in addition to git-
         | bracnehs)?
        
         | killerstorm wrote:
         | Yeah, also JetBrains IDEs like IntelliJ have very nice merge
         | UI.
         | 
         | Perhaps the value of doing it on SCM level is that it can
         | remember what you did. Git has some not-so-nice edge cases.
        
         | hyttioaoa wrote:
         | I often find myself using the gitlens in vscode, to do
         | something similar. I'd compare the working tree to the common
         | base. Then I have the left pane with what's already in the
         | base, the right pane is editable with the result in it.
         | 
         | It's nice to have all the LSP features available too while
         | editing.
        
         | eru wrote:
         | I agree!
         | 
         | This is all good advice, but these days I just ask Claude for
         | solving merge conflicts, and I can't remember it ever going
         | wrong.
         | 
         | Almost all merge conflicts I see in practice are fairly
         | mechanically solved.
        
         | PunchyHamster wrote:
         | There isn't. Git plumbing is elastic enough that you could have
         | way different workflows built on top of it and still have repo
         | that is usable by other tools.
         | 
         | Hell, git tools themselves offer a ton of customization, you
         | can have both display and diff command different than the
         | builtin very easily.
         | 
         | Some of Git defaults and command syntax might suck but all of
         | that can be fixed without touching repo format
        
         | commandersaki wrote:
         | Is there any FOSS tool that gives a 4-pane merge, or even
         | 3-pane so long as the third pane would show the resulting
         | change. That would be so handy.
        
       | lemonwaterlime wrote:
       | See vim-mergetool[1]. I use it to manage merge conflicts and it's
       | quite intuitive. I've resolved conflicts that other people didn't
       | even want to touch.
       | 
       | [1]: https://github.com/samoshkin/vim-mergetool
        
         | mentalgear wrote:
         | Looks like vscode diff view .
        
       | skybrian wrote:
       | It sounds interesting but the main selling point doesn't really
       | reasonate:
       | 
       | If you haven't resolved conflicts then it probably doesn't
       | compile and of course tests won't pass, so I don't see any point
       | in publishing that change? Maybe the commit is useful as a
       | temporary state locally, but that seems of limited use?
       | 
       | Nowadays I'd ask a coding agent to figure out how to rebase a
       | local branch to the latest published version before sending a
       | pull request.
        
         | dcre wrote:
         | This is a reasonable reaction -- pretty sure I felt the same
         | way when I heard about jujutsu's first-class conflicts[0] --
         | but it turns out to be really useful not to be stuck inside an
         | aberrant state while conflicts are in the process of being
         | resolved.
         | 
         | [0]: https://docs.jj-vcs.dev/latest/conflicts/
        
         | dzaima wrote:
         | In git if you, say, do some `git rebase -i`, edit some commit,
         | continue the rebase, and hit a conflict, and realize you edited
         | something wrong that caused the conflict, your only option is
         | aborting the entire rebase and starting over and rebuilding all
         | changes you did.
         | 
         | In jj, you just have a descending conflict, and if you edit the
         | past to no longer conflict the conflict disappears; kinda as if
         | you were always in interactive rebase but at all points have
         | the knowledge of what future would look like if you `git rebase
         | --continue`d.
         | 
         | Also really nice for reordering commits which can result in
         | conflicts, but leaves descendants non-conflicting, allowing
         | delaying resolving the conflicts after doing other stuff, or
         | continuing doing some reordering instead of always starting
         | from scratch as with `git rebase -i`.
        
       | WCSTombs wrote:
       | For the conflicts, note that in Git you can do
       | git config --global merge.conflictstyle diff3
       | 
       | to get something like what is shown in the article.
        
         | NetOpWibby wrote:
         | This should be the default.
         | 
         | Nearly every time I see a complaint about git, someone comes
         | through with a command like this. Is there a collection of
         | similar tips that makes git better to use? If not, there should
         | be.
        
       | mentalgear wrote:
       | > [CRDT] This means merges don't need to find a common ancestor
       | or traverse the DAG. Two states go in, one state comes out, and
       | it's always correct.
       | 
       | Well, isn't that what the CRDT does in its own data structure ?
       | 
       | Also keep in mind that syntactic correctness doesn't mean
       | functional correctness.
        
         | Retr0id wrote:
         | Yes.
         | 
         | There are many ways to instantiate a CRDT, and a trivial one
         | would be "last write wins" over the whole source tree state.
         | LWW is obviously not what you'd want for source version
         | control. It is "correct" per its own definition, but it is not
         | useful.
         | 
         | Anyone saying "CRDTs solve this" without elaborating on the
         | specifics of their CRDT is not saying very much at all.
        
         | mweidner wrote:
         | You can think of the semantics (i.e., specification) of any
         | CRDT as a function that inputs the operation history DAG and
         | outputs the resulting user-facing state. However, algorithms
         | and implementations usually have a more programmatic
         | description, like "here is a function `(internal state, new
         | operation) -> new internal state`", both for efficiency (update
         | speed; storing less info than the full history) and because
         | DAGs are hard to reason about. But you do see the function-of-
         | history approach in the paper "Pure Operation-Based Replicated
         | Data Types" [1].
         | 
         | [1] https://arxiv.org/abs/1710.04469
        
       | alunchbox wrote:
       | Jujutsu honestly is the future IMO, it already does what you have
       | outlined but solved in a different way with merges, it'll let you
       | merge but outline you have conflicts that need to be resolved for
       | instance.
       | 
       | It's been amazing watching it grow over the last few years.
        
         | aduwah wrote:
         | The only reason I have not defaulted to jj already is the
         | inability to be messy with it. Easy to make mistakes without
         | "git add"
        
           | dzaima wrote:
           | But you do have the op log, giving you a full copy of the log
           | (incl. the contents of the workspace) at every operation, so
           | you can get out of such mistakes with some finagling.
           | 
           | You can choose to have a workflow where you're never directly
           | editing any commit to "gain back autonomy" of the working
           | copy; and if you really want to, with some scripting, you can
           | even emulate a staging area with a specially-formatted commit
           | below the working copy commit.
        
           | llyama wrote:
           | You can be messy. The lack of an explicit staging area
           | doesn't restrict that. `jj commit` gives the same mental
           | model for "I want to commit 2 files from the 5 I've changed".
        
           | nchmy wrote:
           | You're mistaken. I'm an absolute version control slob. JJ
           | allows me to continue like that yet also collaborate with
           | others. It tracks literally everything so I can not only
           | split, squash, and rebase things to wherever they need to be,
           | but can also rollback/restore/recover anything from either
           | the repo-wide oplog or revision-specific evolog
           | 
           | You really ought to dive in deeper. jjui makes it all vastly
           | simpler
        
           | simonmic wrote:
           | You can turn off the auto-tracking, and add your files
           | manually.
        
       | phtrivier wrote:
       | A suggestion : is there any info to provide in diffs that is
       | faster to parse than "left" and "right" ? Can the system have
       | enough data to print "bob@foo.bar changed this" ?
        
         | dkdbejwi383 wrote:
         | Or even just "the branch you're on" and "the branch being
         | merged into yours"
        
       | lasgawe wrote:
       | This is a really interesting and well thought out idea,
       | especially the way it turns conflicts into something informative
       | instead of blocking. The improved conflict display alone makes it
       | much easier to understand what actually happened. I think using
       | CRDTs to guarantee merges always succeed while still keeping
       | useful history feels like a strong direction for version control.
       | Looks like a solid concept!
        
       | a-dub wrote:
       | doesn't the side by side view in github diff solve this?
       | 
       | conflict free merging sounds cool, but doesn't that just mean
       | that that a human review step is replaced by "changes become
       | intervals rather than collections of lines" and "last set of
       | intervals always wins"? seems like it makes sense when the
       | conflicts are resolved instantaneously during live editing but
       | does it still make sense with one shot code merges over long
       | intervals of time? today's systems are "get the patch right" and
       | then "get the merge right"... can automatic intervalization be
       | trusted?
       | 
       | edit: actually really interesting if you think about it. crdts
       | have been proven with character at a time edits and use of the
       | mouse select tool.... these are inherently intervalized (select)
       | or easy (character at a time). how does it work for larger
       | patches can have loads of small edits?
        
       | socalgal2 wrote:
       | > [CRDT] This means merges don't need to find a common ancestor
       | or traverse the DAG. Two states go in, one state comes out, and
       | it's always correct.
       | 
       | Funny, there was just a post a couple of days ago how this is
       | false.
       | 
       | https://news.ycombinator.com/item?id=47359712
        
       | monster_truck wrote:
       | Not this again
        
       | codemog wrote:
       | Nobody should have these types of problems in the age of AI
       | agents. This kind of clean up and grunt work is perfect for AI
       | agents. We don't need new abstractions.
        
         | twsted wrote:
         | Version control systems are more important than ever with AI.
        
       | BlueHotDog2 wrote:
       | This is cool and i keep thinking about CRDTs as a baseline for
       | version control, but CRDTs has some major issues, mainly the fact
       | that most of them are strict and "magic" in the way they actually
       | converge(like the joke: CRDTs always converge, but to what). i
       | didn't read if he's using some special CRDT that might solve for
       | that, but i think that for agentic work especially this is very
       | interesting
        
       | bob1029 wrote:
       | I think there are still strong advantages to the centralized
       | locking style of collaboration. The challenge is that it seems to
       | work best in a setting where everyone is in the same physical
       | location while they are working. You can break a lock in 30
       | seconds with your voice. Locking across time zones and date lines
       | is a nonstarter by comparison.
        
         | fn-mote wrote:
         | It seems like in a reasonable sized org you should not be
         | merging so often that "centralized locking ... across time
         | zones" should be an issue.
         | 
         | Are people really merging that often? What is being merged? Doc
         | fixes?
        
           | jsmith45 wrote:
           | The file locking approach is one used by centralized version
           | control systems, and are mostly used in the everybody commits
           | directly to trunk style of development. In those environments
           | merging isn't much of a thing. (Of course this style also
           | comes with other challenges, especially around code review,
           | as it means either people are constantly commit unreviewed
           | code, or you develop some other system to pre-review code,
           | which can slow down the speed of checking things in.)
           | 
           | This approach is actually fairly desirable for assets types
           | that cannot be easily merged, like images, sounds, videos,
           | etc. You seldom actually want multiple people working on any
           | one file of those at the same time, as one or the other of
           | their work will either be wasted or have to be re-done.
        
       | sibeliuss wrote:
       | Why must everyone preprocess their blog posts with ChatGPT? It is
       | such a disservice to ones ideas.
        
         | alansaber wrote:
         | Because writing is really hard.
        
       | newsoftheday wrote:
       | OK, I'll stick with git.
        
       | nkmnz wrote:
       | I don't quite understand how CRDTs should help with merges. The
       | difficult thing about merges is not that two changes touch the
       | same part of the code; the difficult thing is that two changes
       | can touch different parts of the code and still break each other
       | - right?
        
         | AceJohnny2 wrote:
         | Eh. It's a matter of visible pain vs invisible pain.
         | 
         | Developers are quite familiar with Merge Conflicts and the
         | confusing UI that git (and SVN before it, in my experience)
         | gives you about them. The "ours vs theirs" nomenclature which
         | doesn't help, etc. This is something that VCSs can improve on,
         | QED this post.
         | 
         | Vs the scenario you're describing (what I call Logical
         | Conflicts), where two changes touching different parts of the
         | code (so it doesn't emerge as a Merge Conflict) but still
         | breaking each other. Like one change adding a function call in
         | one file but another change changing the API in a different
         | file.
         | 
         | These are painful in a different way, and not something that a
         | simple text-based version control (which is all of the big
         | ones) can even see.
         | 
         | Indeed, CRDTs do not help with Logical Conflicts.
        
           | nkmnz wrote:
           | Thank you for the clarification. I agree that the current
           | state of the art to show conflicts _in the same part of the
           | code_ is not sufficient, so any improvement with regard to
           | that is welcome. Still, I'm more looking for solutions with
           | the Logical Conflicts.
        
       | gavinhoward wrote:
       | Bram Cohen is awesome, but this feels a little bare. I've put
       | much more thought into version control ([1]), including the use
       | of CRDTs (search for "# History Model" and read through the
       | "Implementing CRDTs" section).
       | 
       | [1]: https://gavinhoward.com/uploads/designs/yore.md
        
         | AceJohnny2 wrote:
         | That's worth making a separate post! (and I recommend rendering
         | it to HTML)
         | 
         | But "bare" is part of the value of Cohen's post, I think. When
         | you want to publicize a paradigm shift, it helps to make it in
         | small, digestible chunks.
        
         | 63stack wrote:
         | Is this the Bram Cohen who made bittorrent? There is
         | surprisingly little information on this page.
        
           | vessenes wrote:
           | Yes
        
           | esafak wrote:
           | Yes, just look at his Github page.
        
       | MattCruikshank wrote:
       | For anyone who thinks diff / merge should be better - try Beyond
       | Compare from Scooter Software.
        
       | steveharing1 wrote:
       | Git is my first priority until or unless i see anything more
       | robust than this one.
        
       | barrkel wrote:
       | I don't really get the upside of focus on CRDTs.
       | 
       | The semantic problem with conflicts exists either way. You get a
       | consistent outcome and a slightly better description of the
       | conflict, but in a way that possibly interleaves changes, which I
       | don't think is an improvement at all.
       | 
       | I am completely rebase-pilled. I believe merge commits should be
       | avoided at all costs, every commit should be a fast forward
       | commit, and a unit of work that can be rolled back in isolation.
       | And also all commits should be small. Gitflow is an anti-pattern
       | and should be avoided. Long-running branches are for patch
       | releases, not for feature development.
       | 
       | I don't think this is the future of VCS.
       | 
       | Jujutsu (and Gerrit) solves a real git problem - multiple
       | revisions of a change. That's one that creates pain in git when
       | you have a chain of commits you need to rebase based on feedback.
        
         | gzread wrote:
         | People see that CRDTs have no conflicts and proclaim them as
         | the solution to all problems, not seeing that some problems
         | inherently have conflicts and either can't be represented by
         | CRDTs at all, or that the use of CRDTs resolves conflicts in a
         | way that's worse than if you actually thought about conflict
         | resolution. E.g. that multiplayer text editor that interleaved
         | characters from simultaneous edits.
        
         | IgorPartola wrote:
         | I used to use rebase much more than merge but have grown to be
         | more nuanced over the years:
         | 
         | Merge commits from main into a feature branch are totally fine
         | and easier to do than rebasing. After your feature branch is
         | complete you can do one final main-to-feature-branch merge and
         | then merge the feature branch into main with a squash commit.
         | 
         | When updating any branch from remote, I always do a pull rebase
         | to avoid merge commits from a simple pull. This works well
         | 99.99% of the time since what I have changed vs what the remote
         | has changed is obvious to me.
         | 
         | When I work on a project with a dev branch I treat feature
         | branches as coming off dev instead of main. In this case I
         | merge dev into feature branches, then merge feature branches
         | into dev via a squash commit, and then merge main into dev and
         | dev into main as the final step. This way I have a few merge
         | commits on dev and main but only when there is something like
         | an emergency fix that happens on main.
         | 
         | The problem with always using a rebase is that you have to
         | reconcile conflicts at every commit along the way instead of
         | just the final result. That can be a lot more work for commits
         | that will never actually be used to run the code and can in
         | fact mess up your history. Think of it like this:
         | 
         | 1. You create branch foo off main.
         | 
         | 2. You make an emergency commit to main called X.
         | 
         | 3. You create commits A, B, and C on foo to do your feature
         | work. The feature is now complete.
         | 
         | 4. You rebase foo off main and have to resolve the conflict
         | introduced by X happening before A. Let's say it conflicts with
         | all three of your commits (A, B, and C).
         | 
         | 5. You can now merge foo into main with it being a fast forward
         | commit.
         | 
         | Notice that at no point will you want to run the codebase such
         | that it has commits XA or XAB. You only want to run it as XABC.
         | In fact you won't even test if your code works in the state XA
         | or XAB so there is little point in having those checkpoints.
         | You care about three states: main before any of this happened
         | since it was deployed like that, main + X since it was deployed
         | like that, and main with XABC since you added a feature. git
         | blame is really the only time you will ever possibly look at
         | commits A and B individually and even then the utility of it is
         | so limited it isn't worth it.
         | 
         | The reality is that if you only want fast forward commits,
         | chances are you are doing very little to go back and extract
         | code out of old versions a of the codebase. You can tell this
         | by asking yourself: "if I deleted all my git history from main
         | and have just the current state + feature branches off it, will
         | anything bad happen to my production system?" If not, you are
         | not really doing most of what git can do (which is a good
         | thing).
        
           | barrkel wrote:
           | I am now wholly bought into the idea of having a feature
           | branch with (A->B->C) commits is an anti-pattern.
           | 
           | Instead, if the feature doesn't work without the full chain
           | of A+B+C, either the code introduced in A+B is orphaned
           | except by tests and C joins it in; or (and preferably for a
           | feature of any significance), A introduces a feature flag
           | which disables it, and a subsequent commit D removes the
           | feature flag, after it is turned on at a time separate to
           | merge and deploy.
        
             | IgorPartola wrote:
             | I treat each feature branch as my own personal playground.
             | There should be zero reason for anyone to ever look at it.
             | Sometimes they aren't even pushed upstream. Otherwise, just
             | work on main with linear history and feature flags and
             | avoid all this complexity that way.
             | 
             | Just like you don't expect someone else's local codebase to
             | always be in a fully working state since they are actively
             | working on it, why do you expect their working branch to be
             | in a working state?
        
           | DSMan195276 wrote:
           | I think you're somewhat missing the point - if the code from
           | A and B only works if joined with C, then you should squash
           | them all into one commit so that they can't be separated. If
           | you do that then the problem you're describing goes away
           | since you'll only be rebasing a single commit anyway.
           | 
           | Whether this is valuable is up to you, but IMO I'd say it's
           | better practice than not. People do dumb things with the
           | history and it's harder to do dumb things if the commits are
           | self-contained. Additionally if a feature branch includes
           | multiple commits + merges I'd much rather they squash that
           | into a single commit (or a couple logical commits) instead of
           | keeping what's likely a mess of a history anyway.
        
             | IgorPartola wrote:
             | That is literally what I advocate you do for the main
             | branch. A feature branch is allowed to have WIP commits
             | that make sense for the developer working on the branch
             | just like uncommitted code might not be self contained
             | because it is WIP. Once the feature is complete, squash it
             | into one commit and merge it into main. There is very
             | little value to those WIP commits (rare case being when you
             | implement algorithm X but then change to Y and later want
             | to experiment with X again).
        
               | bathwaterpizza wrote:
               | One downside of squash merging is that when you need to
               | split your work across branches, so that they're
               | different PRs, but one depends on the other, then you
               | have to do a rebase after every single one which had
               | dependencies is merged.
        
               | IgorPartola wrote:
               | When that happens I essentially pick one of the branches
               | as the trunk for that feature and squash merge into that,
               | test it, then merge a clean history into main.
        
         | hackrmn wrote:
         | When you say "unit of work", unit of _which_ work are you
         | referring to? The problem with rebasing is that it takes one
         | set of snapshots and replays them on top of another set, so you
         | end up with two "equivalent" units of work. In fact they're
         | _the same_ indeed -- the tree objects are shared, except that
         | if by "work" you mean changes, Git is going to tell you two
         | different histories, obviously.
         | 
         | This is in contrast with [Pijul](https://pijul.org) where
         | changes are patches and are commutative -- you can apply an
         | entire set and the result is supposed to be equivalent
         | regardless of the order the patches are applied in. Now _that_
         | is unit of work" I understand can be applied and undone in
         | "isolation".
         | 
         | Everything else is messy, in my eyes, but perhaps it's orderly
         | to other people. I mean it would be nice if a software system
         | defined with code could be expressed with a set of independent
         | patches where each patch is "atomic" and a feature or a fix
         | etc, to the degree it is possible. With Git, that's a near-
         | impossibility _in the graph_ -- sure you can cherry-pick or
         | rebase a set of commits that belong to a feature (normally on a
         | feature branch), but _why_?
        
           | barrkel wrote:
           | By "unit of work", I mean the atomic delta which can, on its
           | own, become part of the deployable state of the software. The
           | thing which has a Change-Id in Gerrit.
           | 
           | The delta is the important thing. Git is deficient in this
           | respect; it doesn't model a delta. Git hashes identify the
           | tip of a tree.
           | 
           | When you rebase, you ought to be rebasing the change, the
           | unit of work, a thing with an identity separate and
           | independent of where it is based from.
           | 
           | And this is something that the jujutsu / Gerrit model fixes.
        
         | josephg wrote:
         | CRDTs should be able to give you better merge and rebase
         | behaviour. They essentially make rebase and merge commits the
         | same thing - just different views on a commit, and potentially
         | different ways to present the conflict. CRDTs also behave
         | better when commits get merged multiple times in complex graphs
         | - you don't run into the problem of commits conflicting with
         | themselves.
         | 
         | You should also be able to roll back a single commit or chain
         | of commits in a crdt pretty easily. It's the same as the undo
         | problem in collaborative editors - you just apply the inverse
         | of the operation right after the change. And this would work
         | with conflicts - say commits X and Y+Z conflict, and you're in
         | a conflicting state, you could just roll back commit Y which is
         | the problem, while keeping X and Z. And at no point do you need
         | to resolve the conflict first.
         | 
         | All this requires good tooling. But in general, CRDTs can store
         | a superset of the data stored by git. And as a result, they can
         | do all the same things and some new tricks.
        
           | sroussey wrote:
           | In theory, maybe. In practice... last write wins (LWW) is a
           | CFDT operator, so replace every mention of CRDT with LWW and
           | issues will more obvious.
           | 
           | Really though, the problem with merges is not conflicts, it's
           | when the merged code is wrong but was correct on both sides
           | before the merge. At least a conflict draws your attention.
           | 
           | When I had several large (smart but young) teams merging left
           | and right this would come up and they never checked merged
           | code.
           | 
           | Multiply by x100 for AI slop these days. And I see people
           | merge away when the AI altered tests to suit the broken code.
        
             | josephg wrote:
             | > In practice... last write wins (LWW) is a CFDT operator,
             | so replace every mention of CRDT with LWW and issues will
             | more obvious.
             | 
             | Yeah. A lot of people are also confused by the twin
             | meanings of the word "conflict". The "C" in CRDT stands for
             | "Conflict (free)", but that really means "failure free".
             | Ie, given any two concurrent operations, there is a well
             | defined "merge" of the two operations. The merge operation
             | can't fail.
             | 
             | The second meaning is "conflict" as in "git commit
             | conflict", where a merge gets marked as requiring human
             | intervention.
             | 
             | Once you define the terms correctly, its possible to write
             | a CRDT-with-commit-conflicts. Just define a "conflict
             | marker" which are sometimes emitted when merging. Then
             | merging can be defined to always succeed, sometimes
             | emitting conflict markers along the way.
             | 
             | > Really though, the problem with merges is not conflicts,
             | it's when the merged code is wrong but was correct on both
             | sides before the merge.
             | 
             | CRDTs have strictly more information about whats going on
             | than Git does. At worst, we should be able to remake git on
             | top of CRDTs. At best, we can improve the conflict
             | semantics.
        
               | skydhash wrote:
               | > CRDTs have strictly more information about whats going
               | on than Git does. At worst, we should be able to remake
               | git on top of CRDTs. At best, we can improve the conflict
               | semantics.
               | 
               | That is a worthwhile goal, but remember that code is just
               | a notation for some operation, it's not the operation
               | itself (conducted by a processor). Just like a map is a
               | description of a place, not the place itself. So
               | semantics exists outside of it and you can't solve
               | semantics issue with CRDTs.
               | 
               | As code is formal and structured, version control
               | conflict is a signal, not a nuisance. It may be crude,
               | but it's like a canari in a mine. It lets you know that
               | someone has modified stuff you've worked on in your
               | patch. And then it's up to you to resolve the probable
               | semantics conflicts.
               | 
               | But even if you don't have conflicts, you should check
               | your code after a synchronization as things you rely on
               | may have changed since your last one.
        
             | afiori wrote:
             | being able to customize the chunking/diffing process with
             | something analogous to an lsp would greatly improve this.
             | In my experience a particularly horribly handled case is
             | when eg two branches add two distinct methods/functions in
             | the same file location (especially if there is some
             | boilerplate so that the two blocks share more than a few
             | lines).
             | 
             | a language aware merge could instead produce
             | 
             | >>>> function foo(){ ... } ===== function bar(){ ... }
             | <<<<<<
        
               | mtndew4brkfst wrote:
               | If you haven't heard of it yet, Mergiraf uses tree-sitter
               | grammars to resolve merges using syntax-aware logic and
               | has a pretty good success rate for my work.
        
           | ivlozada wrote:
           | This is the key point. Once your data structure carries the
           | full edit history instead of reconstructing it from DAG
           | traversal, rebase and merge become different views of the
           | same operation. Not fundamentally different operations with
           | different failure modes.
           | 
           | The weave approach moves ordering into the data itself.
           | That's the same insight that matters in any system that needs
           | deterministic ordering across independent participants: put
           | the truth in the structure, not in the topology of how it was
           | assembled.
        
             | gf000 wrote:
             | Afaik pijul already does that though
        
         | bawolff wrote:
         | > Jujutsu (and Gerrit) solves a real git problem - multiple
         | revisions of a change. That's one that creates pain in git when
         | you have a chain of commits you need to rebase based on
         | feedback.
         | 
         | I use gerrit extensively... well it does "solve" that problem,
         | i think its far from an ideal solution. It becomes a mess once
         | you have patches depending on other patches and you have to
         | edit a patch somewhere in the stack, and it very much feels
         | bolted on to git. Don't get me wrong, it works, but i think
         | fresh new ideas on how to solve this problem are still needed.
        
       | catlifeonmars wrote:
       | Can we stop using line-oriented diffs in favor of AST-oriented
       | diffs?
       | 
       | Is it just lack of tooling, or is there something fundamentally
       | better about line-oriented diffs that I'm missing? For the
       | purpose of this question I'm considering line-oriented as a
       | special case of AST-oriented where the AST is a list of lines
       | (anticipating the response of how not all changes are
       | syntactically meaningful or correct).
        
       | Aperocky wrote:
       | Outside of the merit of the idea itself, I thought I was going to
       | look at a repository at least as complete as Linus when he
       | released git after 3 weeks, especially with the tooling we had
       | today.
       | 
       | Slightly disappointed to see that it is a 470 line python file
       | being touted as "future of version control". Plenty of things are
       | good enough in 470 lines of python, even a merge conflict
       | resolver on top of git - but it looks like it didn't want
       | anything to do with git.
       | 
       | Prototyping is almost free these days, so not sure why we only
       | have the barest of POC here.
        
         | ithkuil wrote:
         | It clearly says in the article that this is just a demo
        
           | mtndew4brkfst wrote:
           | A demo as "the future of" something doesn't really resonate
           | with me. It's like saying a melodic motif and a couple well-
           | written lines of lyrics are "the future of" my new music
           | career.
        
             | ithkuil wrote:
             | I guess it depends on how you parse "the future of X".
             | 
             | To me it sounds like "This is how I imagine the future of
             | X", i.e. a preview of a possible future.
        
       | merlindru wrote:
       | I recently found a project called sem[1] that does git diffs but
       | is aware of the language itself, giving feedback like "function
       | validateToken added", "variable xyzzy removed", ...
       | 
       | i think that's where version control is going. especially useful
       | with agents and CI
       | 
       | [1] https://ataraxy-labs.github.io/sem/
        
       | lowbloodsugar wrote:
       | Araxis merge. Four views. Theirs, ours, base and "what you did so
       | far in this damned merge hell".
        
       | echrisinger wrote:
       | Has anyone considered a VCS that integrates more vertically with
       | the source code through ASTs?
       | 
       | IE if I change something in my data model, that change & context
       | could be surfaced with agentic tooling.
        
         | conartist6 wrote:
         | That's me, with BABLR. Working on getting a beta release
         | announced in the next few days.
        
       | aggregator-ios wrote:
       | What CRDT's solve is conflicts at the system level. Not at the
       | semantic level. 2 or more engineers setting a var to a different
       | value cannot be handled by a CRDT.
       | 
       | Engineer A intended value = 1
       | 
       | Engineer B intended value = 2
       | 
       | CRDT picks 2
       | 
       | The outcome could be semantically wrong. It doesn't reflect the
       | intent.
       | 
       | I think the primary issue with git and every other version
       | control is the terrible names for everything. pull, push, merge,
       | fast forward, stash, squash, rebase, theirs, ours, origin,
       | upstream and that's just a subset. And the GUI's. They're all
       | very confusing even to engineers who have been doing this for a
       | decade. On top of this, conflict resolution is confusing because
       | you don't have any prior warnings.
       | 
       | It would be incredibly useful if _before_ you were about to edit
       | a file, the version control system would warn you that someone
       | else has made changes to it already or are actively working on
       | it. In large teams, this sort of automation would reduce
       | conflicts, as long as humans agree to not touch the same file.
       | This would also reduce the amount of quality regressions that
       | result from bad conflict resolutions.
       | 
       | Shameless self plug: I am trying to solve both issues with a
       | simpler UI around git that automates some of this and it's free.
       | https://www.satishmaha.com/BetterGit
        
         | jnsie wrote:
         | > It would be incredibly useful if before you were about to
         | edit a file, the version control system would warn you that
         | someone else has made changes to it already or are actively
         | working on it. In large teams, this sort of automation would
         | reduce conflicts, as long as humans agree to not touch the same
         | file. This would also reduce the amount of quality regressions
         | that result from bad conflict resolutions.
         | 
         | Bringing me back to my VSS days (and I'd much rather you
         | didn't)
        
           | aggregator-ios wrote:
           | I knew I should have put a trigger warning, because I was
           | thinking of this as I was typing it. Sorry!
        
         | mbfg wrote:
         | well, the mismatch here is widened by the fact that almost
         | everyone it seems uses git with a central, prominent, visible,
         | remote repository. Where as git was developed with the a true
         | distributed vision. Now sure that truely distributed thing only
         | becomes final when it reaches some 'central' repo, but it's
         | quite a big different than we all do.
        
         | j1elo wrote:
         | For that you need a _very centralized_ VCS, not a decentralized
         | one. Perforce allows you to lock a file so everybody else
         | cannot make edits to it. If they implemented more fine-grained
         | locking within files, or added warnings to other users trying
         | to check them out for edits, they 'd be just where you want a
         | VCS to be.
         | 
         | How, or better yet, why would Git warn you about a potential
         | conflict beforehand, when the use case is that everyone has a
         | local clone of the repo and might be driving it towards
         | different directions? You are just supposed to pull commits
         | from someone's local branch or push towards one, hence the
         | wording. The fact that it makes sense to cooperate and work on
         | the same direction, to avoid friction and pain, is just a
         | natural accident that grows from the humans using it, but is
         | not something ingrained in the design of the tool.
         | 
         | We're collectively just using Git for the silliest and simplest
         | subset of its possibilities -a VCS with a central source of
         | truth-, while bearing the burden of complexity that comes with
         | a tool designed for distributed workloads.
        
         | sensanaty wrote:
         | I haven't used them, but doesn't SVN or Mercurial do something
         | like this? It blocks people from working on a file by locking
         | them, the problem is that in large teams there are legitimate
         | reasons for multiple people to be working on the same files,
         | especially something like a large i18n file or whatever.
        
         | josephg wrote:
         | > CRDT picks 2
         | 
         | They don't have to.
         | 
         | The crdt library knows that value is in conflict, and it
         | decides what to do about it. Most CRDTs are built for realtime
         | collab editing, where picking an answer is an acceptable
         | choice. But the crdt can instead add conflict marks and make
         | the user decide.
         | 
         | Conflicts are harder for a crdt library to deal with - because
         | you need to keep merging and growing a conflict range. And do
         | that in a way that converges no matter the order of operations
         | you visit. But it's a very tractable problem - someone's just
         | gotta figure out the semantics of conflicts in a consistent way
         | and code it up. And put a decent UI on top.
        
         | senfiaj wrote:
         | Yeah, same thoughts. I also think semantic merge is the best.
         | Also it would be nice if you could add a plugin for custom
         | binary file formats, such as sqlite (which obviously can't be
         | merged like a text file).
        
       | injidup wrote:
       | I'm confused about what this solves. They give the example of
       | someone editing a function and someone deleting the same function
       | and claim that the merge never fails and then go on to
       | demonstrate that indeed rightly the merges still fails. There are
       | still merge markers in the sources. What is the improvement
       | exactly?
        
         | galkk wrote:
         | Yeah, the author fails to present his case even in the intro
         | 
         | > A CRDT merge always succeeds by definition, so there are no
         | conflicts in the traditional sense -- the key insight is that
         | changes should be flagged as conflicting when they touch each
         | other, giving you informative conflict presentation on top of a
         | system which never actually fails. This project works that out.
         | 
         | It has clear contradiction. Crdt always succeed by definition,
         | no conflicts in traditional sense so (rephrasing) conflicting
         | changes are marked as conflicted. Emm, like in any other source
         | control?
         | 
         | In fact, after rereading that intro while writing that answer I
         | start suspect at least smell of an ai writing.
        
           | fleebee wrote:
           | The README of the repo offers a hint:
           | 
           | > _The code in this project was written artisanally. This
           | README was not._
        
           | josephg wrote:
           | The benefit of using a crdt for this is that you can get
           | better merge semantics. Rebase and merge become the same
           | thing. Commits can't somehow conflict with themselves. You
           | can have the system handle 2 non conflicting changes on the
           | same line of code if you want. You can keep the system in a
           | conflict state and add more changes if you want to. Or undo
           | just a single commit from a long time ago. And you can put
           | non text data in an crdt and have all the same merge and
           | branching functionality.
        
       | ballsweat wrote:
       | Everyone should vibe code a VCS from scratch in their fave
       | language.
       | 
       | It's an awesome weekend project, you can have fun visualizing
       | commits in different ways (I'm experimenting with shaders), and
       | importantly:
       | 
       | This is the way forward. So much software is a wrapper around S3
       | etc. now is your chance to make your own toolset.
       | 
       | I imagine this appeals more to DIYer types (I use Pulsar IDE lol)
        
       | braidedpubes wrote:
       | Do I have it right that it's basically timestamp based, except
       | not based on our clocks but one it manages itself?
       | 
       | So as long as all updates have been sent to the server from all
       | clients, it will know what "time" each character changed and be
       | able to merge automatically.
       | 
       | Is that it basically?
        
       | shitfilleddonut wrote:
       | It seems more like the past of version control
        
       | EGreg wrote:
       | I remember I met Bram Cohen (of Bittorent fame!) around 15 years
       | ago. Around that time is when I had started building web-based
       | distributed collaborative systems, starting with Qbix.com and
       | then spun off a company to build blockchain-based smart contracts
       | through Intercoin.org etc.
       | 
       | Anyway, I wanted to suggest a radical idea based on my
       | experience:
       | 
       | Merges are the wrong primitive.
       | 
       | What organizations (whethr centralized or distributed projects)
       | might actually need is:
       | 
       | 1) Graph Database - of Streams and Relations
       | 
       | 2) Governance per Stream - eg ACLs
       | 
       | A code base should be automatically turned into a graph database
       | (functions calling other functions, accessing configs etc) so we
       | know exactly what affects what.
       | 
       | The concept of what is "too near" each other mentioned in the
       | article is not necessarily what leads to conflicts. Conflicts
       | actually happen due to conflicting graph topology and propagating
       | changes.
       | 
       | People should be able to clone some stream (with permission) and
       | each stream (node in the graph) can be versioned.
       | 
       | Forking should happen into workspaces. Workspaces can be
       | GOVERNED. Publishing some version of a stream just means relating
       | it to your stream. Some people might publish one version, others
       | another.
       | 
       | Rebasing is a first-class primitive, rather than a form of
       | merging. A merge is an extremely privileged operation from a
       | governance point of view, where some actor can just "push" (or
       | "merge") thousands of commits. The more commits, the more chance
       | of conflicts.
       | 
       | The same problem occurs with CRDTs. I like CRDTs, but reconciling
       | a big netsplit will result in merging strategies that create lots
       | of unintended semantic side effects.
       | 
       | Instead, what if each individual stream was guarded by policies,
       | there was a rate limit of changes, and people / AIs rejected most
       | proposals. But occasionally they allow it with M of N sign offs.
       | 
       | Think of chatgpt chats that are used to modify evolving
       | artifacts. People and bots working together. The artifacts are
       | streams. And yes, this can even be done for codebases. It isnt
       | about how "near" things are in a file. Rather it is about whether
       | there is a conflict on a graph. When I modify a specific function
       | or variable, the system knows all of its callers downstream. This
       | is true for many other things besides coding too. We can also
       | have AI workflows running 24/7 to try out experiments as a swarm
       | in sandboxes, generate tests and commit the results that pass.
       | But ultimately, each organization determines whether they want to
       | rebase their stream relations to the next version of something or
       | not.
       | 
       | That is what I'm building now with https://safebots.ai
       | 
       | PS: if anyone is interested in this kind of stuff, feel free to
       | schedule a calendly meeting w me on that site. I just got started
       | recently, but I'm dogfooding my own setup and using AI swarms
       | which accelerates the work tremendously.
        
       | theknarf wrote:
       | You can't use CRDTs for version control, having conflicts is the
       | whole point of version control. Sometimes two developers will
       | make changes that fundamentally tries to change the code in two
       | different ways, a merge conflict then leaves it up to the
       | developer who is merging/rebasing to make a choice about the
       | semantics of the program they want to keep. A CRDT would just
       | produce garbage code, its fundamentally the wrong solution. If
       | you want better developer UX for merge conflicts then there are
       | both a bunch of tooling on top of Git, as well as other version
       | control systems, that try to present it in a better way; but that
       | has very little to do with the underlaying datastructure. The
       | very fact that cherry-picking and reverting becomes difficult
       | with this approach should show you that its the wrong approach!
       | Those are really easy operations to do in Git.
        
         | tbrownaw wrote:
         | > _You can 't use CRDTs for version control_
         | 
         | You misunderstand what is being proposed.
         | 
         | Using CRDTs to calculate the results of a merge _does not
         | require_ being allowed to commit the results of that
         | calculation, and doesn 't even require that you be able to
         | physically realize the results in the files in your working
         | copy.
         | 
         | .
         | 
         | Consider for example if you want to track and merge scalar
         | values. Maybe file names if you track renames, maybe file
         | properties if you're not just using a text listing (ie
         | .gitattributes) for that, maybe file content hash to decide
         | whether to actually bother running a line-based merge.
         | 
         | One approach is to use what Wikipedia says is called an OR-
         | set[1], with the restriction that a commit can only have a
         | single unique value; if it was previously in the set then it
         | keeps all the same tags, if it wasn't then it gets a new tag.
         | 
         | That restriction is where the necessity of conflict resolution
         | comes in. It doesn't have to be part of the underlying
         | algorithms, just the interface with the outside world.
         | 
         | [1] https://en.wikipedia.org/wiki/Conflict-
         | free_replicated_data_...
        
           | Retr0id wrote:
           | If semantics-layer conflicts still have to be detected
           | somehow, and resolved by hand, what value is the underlying
           | CRDT providing?
        
             | furyofantares wrote:
             | > the result is always the same no matter what order
             | branches are merged in -- including many branches mashed
             | together by multiple people working independently.
        
               | Retr0id wrote:
               | Why is that valuable?
        
               | zephen wrote:
               | Yeah, symmetry is overrated.
               | 
               | Git's merge is _already_ symmetrical for two branches
               | being merged, and that, in and of itself, often leads to
               | problems.
               | 
               | It's completely unclear that extending this to multiple
               | branches would provide any goodness.
        
               | drfloyd51 wrote:
               | It means anyone can fix the conflict. Including a server
               | side AI.
        
               | Retr0id wrote:
               | non sequitur
        
               | SpaceNoodled wrote:
               | I was wondering when someone would try to cram The Slop
               | Machine into this.
        
             | mememememememo wrote:
             | Syntax-only manual merges are just time consuming waste of
             | human time.
             | 
             | I'm a small PR-er so 99% of the time it is Syntax. If if it
             | is semnatic at all often then try trunk based development.
        
               | Retr0id wrote:
               | The CRDT isn't syntax-aware either
        
               | mememememememo wrote:
               | If it is doing what I think CRDT does, and tracking where
               | the user clicked and what they typed, it sort of carries
               | a bit more syntax info. It has a chance to get it right.
               | And often since it does something it turns a figure this
               | shit out with review this.
        
               | vlovich123 wrote:
               | Much better is AST merging (which itself is also more
               | amenable to crdts). But doing this at the text level is
               | doing to be a failed experiment - the value isn't there.
        
             | sigbottle wrote:
             | This was my immediate thought when seeing this post too
             | lol.
        
         | mememememememo wrote:
         | But merging already auto-merges what it can best effort.
         | Conflicts are syntax conflicts not semantic ones.
         | 
         | Therefore you could have automerges that conflict in a way that
         | breaks the code.
         | 
         | Example would be define a global constant in file X. One commit
         | removes it. Another commit on another branch makes use of it in
         | file Y.
         | 
         | OTOH where I get merge conflicts in Git it is usually purely
         | syntax issue that could be solved by a slightly cleverer merge
         | algo. CRDT or semantic merge.
        
         | toomim wrote:
         | Pijul does both. It's a VCS, that is a CRDT, that preserves
         | conflicts until a human resolves them.
         | 
         | Look it up: https://pijul.org
         | 
         | It also makes cherrypicking and rebasing wayyyy easier. You can
         | actually add or remove any set of patches, at any time, on any
         | peer. It's a dramatic model shift -- and is awesome.
        
         | shubhamjain wrote:
         | I would like to point out that Bram Cohen seems to be obsessed
         | with "better merges" and had a verbal spat with Linus on Git
         | when it was just taking off (2007).
         | 
         | https://news.ycombinator.com/item?id=8118817
         | 
         | It's pretty weird that he has gone back to the same idea
         | without understanding why Git's approach is better. I would say
         | VCS is largely a solved problem. You can simplify a few things
         | here and there, maybe improve support for binaries and few
         | other things, but that's almost on the top of existing systems.
         | The foundation is rock solid, so it doesn't sound very sensible
         | to attempt something from ground up.
        
         | masklinn wrote:
         | Both jj and pijul save (~commit) conflicts to be resolved
         | later, rather than require immediate resolution.
         | 
         | And jj was built around rebase being a routine operation, often
         | transparent (cherrypicking being a form of rebasing).
        
       | astrostl wrote:
       | Disagree. We all are -- or should be -- Linux kernel developers.
       | What's more, we should align to a specific and singular VCS
       | worldview informed by BitKeeper, which no longer exists, whether
       | or not we used it. Therefore Git. Thank you for your attention to
       | this matter!
        
         | simultsop wrote:
         | You sound more like a DOS dev instead of linux.
        
       | Ferret7446 wrote:
       | I'm pretty sure jujutsu already does this, and it's interopable
       | with git
        
       | nailer wrote:
       | You're still treating code as text which it isn't (in the same
       | way you wouldn't treat JSON as text) it's actually more like an
       | AST.
       | 
       | Jujutsi (jj) does that. And it's git compatible.
        
         | dcre wrote:
         | I love jj and think virtually every git user should switch to
         | it, but I don't think it treats text as an AST. What do you
         | mean?
        
           | nailer wrote:
           | Ugh you're right. There was a new AST-based version control
           | system that came out a month ago and I couldn't remember the
           | name. I asked an LLM what the name was and repeated the
           | answer the LLM gave me without checking (facepalm).
           | 
           | I may have been thinking of
           | https://github.com/gritzko/librdx/tree/master/be
        
             | WolfeReader wrote:
             | Thanks for the correct link! AST-based version control
             | sounds like a great idea.
        
         | 12_throw_away wrote:
         | No, it doesn't.
        
           | nailer wrote:
           | https://news.ycombinator.com/item?id=47488270
        
       | mweidner wrote:
       | I'm surprised to see the emphasis on tracking lines of text,
       | which ties in to the complexity of merge vs merge-the-other-way
       | vs rebase. If we are committed to enhancing the change history,
       | it seems wiser to go all in and store high-level, semantically-
       | meaningful changes, like "move this code into an `if` block and
       | add `else` block ...".
       | 
       | Consider the first example in the readme, "Left deletes the
       | entire function [calculate]. Right adds a logging line in the
       | middle". If you store the left operation as "delete function
       | calculate<unique identifier>" and the right operation as "add
       | line ... to function calculate", then it's obvious how to get the
       | intended result (calculate is completely deleted), regardless of
       | how you order these operations.
       | 
       | I personally think of version control's job not as collaborating
       | on the actual files, but as collaborating on the canonical order
       | of (high-level) operations on those files. This is what a branch
       | is; merge/rebase/cherry-pick are ways of updating a branch's
       | operation order, and you fix a conflict by adding new operations
       | on top. (Though I argue rebase makes the most sense in this
       | model: your end goal is to append to the main branch.)
       | 
       | Once you have high-level operations, you can start adding high-
       | level conflict markers like "this operation changed the docs for
       | function foo; flag a conflict on any new calls to foo". Note that
       | you will need to remember some info about operations' original
       | context (not just their eventual order in the main branch) to
       | surface these conflicts.
        
       | philwelch wrote:
       | Regardless of the merits of CRDT's, I'm just glad someone is
       | finally trying to create a new version control system. Everyone
       | loves to complain about Git but nobody's actually tried to move
       | beyond it in two decades.
        
         | Nursie wrote:
         | There are those of us who remember the before-times, who I
         | think are in general just happy we have git.
         | 
         | Having lived through sccs, pvcs, SourceSafe, Clearcase and svn
         | (among others), the introduction of lightweight, sane
         | branching, merging, rebasing etc was a revelation.
         | 
         | Yes, there are still things that an adept could do with some of
         | those other systems that git doesn't make easy. For example we
         | have the holy war between those who demand a git repo has a
         | clean history vs those who would rather a revision control
         | system actually stores revision history and forms a record of
         | what really happened. In Rational ClearCase you would use a
         | different config specification depending on your task to
         | programatically select visibility, and hey presto, you have
         | both views available.
         | 
         | (Not that I would wish ClearCase on my worst enemy these days,
         | those config specs were a language in themselves and the amount
         | of times people would get in trouble with them was a real drag,
         | and that's only one of the myriad downsides.)
         | 
         | Then git came along and did away with so much of that
         | complexity that I imagine there are legions of us who think
         | it's good enough (TM) that version control is more or less a
         | solved problem and nothing irks us enough to seek out
         | alternatives.
        
           | philwelch wrote:
           | I can definitely relate to that, and I'm actually quite fond
           | of git myself. I just never expected that people would stop
           | trying to make a better version control system. That's not
           | entirely fair, a lot of work has been invested in Pijul and
           | Fossil, but I would have expected much more interest in
           | alternatives. I remember all of the reasons Git was so new
           | and exciting at the time, but now it feels like we're all
           | locked into it, not out of any deliberate attempt at vendor
           | lockin but out of complacency, and because fewer and fewer of
           | us still remember a time that it felt possible to invent a
           | better version control system.
        
       | KPGv2 wrote:
       | I've tested out jj a bit, and doesn't it solve the issues
       | presented at the link already? I don't work on a team where I
       | need VC better than git, so I just stick with it for my own
       | private use, but I did test jj out of curiosity, and I could've
       | sworn this is basically the same pitch as switching to jj (but
       | for the CRDT under the hood).
        
       | danpalmer wrote:
       | I'm struggling to understand the problem this solves for me. I
       | can see in the abstract why this might be useful, but in practice
       | I don't see the problems.
       | 
       | For me, jj represents a massive step forward from git in terms of
       | usability, usefulness, and solving problems I actually have.
       | 
       | I think the next step forward for version control would be
       | something that works at a lower level, such as the AST. I'd love
       | to see an exploration of what versioning looks like when we don't
       | have files and directories, and a piece of software is one whole
       | tree that can be edited at any level. Things like LightTable and
       | Dark have tried bits of this, it would be good to see a VCS demo
       | of that sort of thing.
        
         | conartist6 wrote:
         | It is coming. Had to build a whole new system of parsers.
        
       | pbw wrote:
       | This sounds good, but I wonder if AI has changed the calculus on
       | conflict resolution. It can not only chase down the conflicting
       | changes, but also read those commit messages and PRs to divine
       | intent. It might be that git is "good enough," given we have AI.
        
       | periodjet wrote:
       | Does this mean he's given up on Chia?
        
       | ReaLNero wrote:
       | Thank you. This sounds like a great approach! I've also been
       | surprised at the mechanical nature that git resolves conflicts
       | in, and the loss of intent when auto-merging.
        
       | Androider wrote:
       | I've had really good success lately with having Claude Code
       | resolve conflicts, to the point that I don't see myself doing
       | manual resolutions going forward.
       | 
       | Set git.conflictStyle to zdiff3 and ask Claude to resolve the
       | conflict, or even better, complete the entire rebase for you. A
       | quick diff sanity check against the merge base of the result
       | takes just a few seconds.
        
         | mememememememo wrote:
         | Thanks literally just used this!
        
       | suralind wrote:
       | Guys, there's a tool called mergiraf[1] that does wonders. I
       | don't remember my last rebase
       | 
       | [1]: https://mergiraf.org/
        
         | senfiaj wrote:
         | Yeah, I also thought that a semantic merge is the best
         | solution. It would be nice if it could be extended with custom
         | formats such as sqlite.
        
       | csomar wrote:
       | I am working on merge conflicts tool[1], so this area is of
       | interest to me. But I fail to see the points of the author. In
       | the first example he gave, git will actually give you three
       | blobs: our, their and ancestor. The ancestor should have the
       | missing information from his example and using code diffs[2], you
       | can see what happened at each blob. Essentially, his blob is a
       | single view of the 3 blobs merged together. Could be useful on
       | the terminal, but if you are using a visual tool, a 3-way diff is
       | always better.
       | 
       | > merges never fail
       | 
       | I am not sure what _never fail_ means here.
       | 
       | > Conflicts are informative, not blocking. The merge always
       | produces a result.
       | 
       | What does this even mean? You merge first and review later? And
       | then other contributor just build on top of your main branch as
       | you decided you want to change your selection?
       | 
       | If you want a smarter merge conflict tool, the one I am
       | enthusiastic about today is Mergiraf:
       | https://codeberg.org/mergiraf/mergiraf
       | 
       | 1: https://codeinput.com/products/merge-conflicts 2:
       | https://codeinput.com/products/merge-conflicts/demo
        
       | donatj wrote:
       | > One idea I'm particularly excited about: rebase doesn't have to
       | destroy history.
       | 
       | I guess I don't understand why not just merge at that point? The
       | point of rebadge is to destroy history...
        
       | modeless wrote:
       | > the key insight is that changes should be flagged as
       | conflicting when they touch each other
       | 
       | Not really. Changes should be flagged as conflicting when they
       | conflict semantically, not when they touch the same lines. A
       | rename of a variable shouldn't conflict with a refactor that
       | touches the same lines, and a change that renames a function
       | should conflict with a change that uses the function's old name
       | in a new place. I don't think I would bother switching to a new
       | VCS that didn't provide some kind of semantic understanding like
       | this.
        
       | chungy wrote:
       | The merge conflict syntax and "doesn't destroy history" both
       | sound exactly like what Fossil does. (Fossil is at
       | https://fossil-scm.org/)
       | 
       | Just a trivial example here:                   lorem ipsum
       | <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<
       | (line 2)         dolor sit amet,         ####### SUGGESTED
       | CONFLICT RESOLUTION follows ###################
       | consectetur adipiscing elit         ||||||| COMMON ANCESTOR
       | content follows ||||||||||||||||||||||||| (line 2)
       | ======= MERGED IN content follows ===============================
       | (line 2)         consectetur adipiscing elit         >>>>>>> END
       | MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        
       | qsera wrote:
       | I think this was something that was _waiting_ for something like
       | LLMs to happen to be solved.
       | 
       | Why aren't AI companies touting "zero-shot"ing huge merge
       | conflicts being resolved by LLMs..
        
         | adastra22 wrote:
         | Have you tried this? It would be a nightmare. The LLM wold
         | "solve" the merge conflict by eliminating the code.
        
           | qsera wrote:
           | But that should make the builds or some tests to fail no? I
           | think we can consider it as a first approximation and proceed
           | to a manual review. It should be a lot easier than manually
           | resolving the difficult merge..
        
             | adastra22 wrote:
             | That's solved by disabling or removing those tests.
             | 
             | I have tried this. It does't work.
        
       | toomim wrote:
       | CRDTs actually have a long history in version control.
       | - The original 1977 version control system, SCCS, was a CRDT:
       | https://braid.org/meeting-60/sccs-is-a-time-collapse            -
       | It called its data structure a 'weave"            - Brahm's old
       | project "Codeville" used a weave for version control            -
       | But then git blew up in popularity.            - The project
       | "DARCS" tried to make a robust "theory of patches," and
       | eventually led to the development of Pijul            - Pijul is
       | a VCS that is a CRDT: https://pijul.org
        
       | jes5199 wrote:
       | This is just CRDT merges and better diffs?? I think the future of
       | version control is much, much weirder than this. Like if you have
       | CRDTs why not have ephemeral branches with real-time
       | collaborative editing and live CI as you type
        
       | forrestthewoods wrote:
       | I hate Git. I think it is mediocre at absolute best.
       | 
       | But nothing in this article is in my top 10. So this doesn't
       | really do anything for me.
       | 
       | All I really want is support for terabytes scale repo history
       | with super fast, efficient, sparse virtual clones. And ideally a
       | global cache for binary blobs with copy-on-write semantics. Which
       | is another way to say I want support for large binary files, and
       | no GitLFS is not sufficient.
        
       | latand666 wrote:
       | This sounds very promising, liked the idea
       | 
       | Is there a CLI like git CLI? Have read the readme but didn't
       | quite get how to use
        
       | latand666 wrote:
       | Have you also thought about multiple staging levels/layers?
       | Sometimes I don't want to commit the work, just to review the AI
       | work piece by piece, moving to the next staging level.
       | 
       | I guess I can do that with plain commits as well and then rewrite
       | history when I need, but I think having multiple staging levels
       | would be more developer friendly especially in the era of AI
       | coding
        
       | QuiCasseRien wrote:
       | I will look at it, it seems interesting. However, i hope a better
       | ending than Pyjul (https://pijul.org/).
       | 
       | I'm no longer waiting for it whereas everything sound awesome :
       | quite no more merge conflict and patches order free.
       | 
       | So sad it's still not production ready.
        
       | PunchyHamster wrote:
       | At this point if your VCS isn't a layer above git plumbing,
       | nobody gonna waste time using it. Especially if the improvements
       | are minor enough that it could be reasonably just a wrapper and
       | still have 90% of the improvements.
       | 
       | > Two opaque blobs. You have to mentally reconstruct what
       | actually happened.
       | 
       | Did you not discover what git diff does ? It's clearer than the
       | presented improvement !
       | 
       | Plenty of 3 way merge tools supported by git too, sure, it's
       | external tool but it's adding one tool rather than upending the
       | workflow
       | 
       | > Conflicts are informative, not blocking. The merge always
       | produces a result. Conflicts are surfaced for review when
       | concurrent edits happen "too near" each other, but they never
       | block the merge itself. And because the algorithm tracks what
       | each side did rather than just showing the two outcomes, the
       | conflict presentation is genuinely useful.
       | 
       | Git merge cache (git rerere) is good enough. Only problem is that
       | it isn't shared but that could be possibly done within git format
       | itself if someone really wanted to
        
         | gavinhoward wrote:
         | > At this point if your VCS isn't a layer above git plumbing,
         | nobody gonna waste time using it.
         | 
         | Probably true, but it's a shame because there are better ways
         | of storing and processing the data, ways that _natively_ handle
         | binary files, semantics, and large files without falling over.
        
       | teeray wrote:
       | > Conventional rebase creates a fictional history where your
       | commits happened on top of the latest main
       | 
       | This is _not_ fiction though. If someone added a param to the
       | functions you're modifying on your branch, rebasing forces you to
       | resolve that conflict _and_ makes the dependency on that explicit
       | and obvious.
        
       | alkonaut wrote:
       | The most infuriating part about git's default behavior is that
       | it's so ignorant about what actual reality users live in.
       | 
       | For example: when merging or rebasing it's really important to
       | know what I did myself, vs what someone else did. Yet it has a
       | really opaque left/right or mine/theirs representation which even
       | _switches meaning_ depending on the operation you are doing.
       | 
       | This isn't even a fundamental diff/patch issue it's just that git
       | shrugs and assumes you want to perform some abstract operation on
       | a DAG of things rather than, you know, rebase your code onto that
       | of your colleagues.
        
       | ata-sesli wrote:
       | The core separation line here seems to be Snapshot vs. Weave. Git
       | treats history as a path between states, but Manyana treats the
       | state as the history.
       | 
       | Since the weave grows with every line ever written, how do you
       | handle "tombstone" (deleted data) bloat? In a decade-old repo
       | with high churn, does the metadata overhead for a single file
       | eventually make it unmanageable compared to Git's "forgetful"
       | snapshotting?
        
       | gitmwnkdkc wrote:
       | People are still having a problem with distributed version
       | control, because some people want to force "the server's" history
       | down the throats of all coworkers.
       | 
       | This can not be solved with tech, it's a people problem.
       | 
       | Conflicts between branches is only a symptom of conflicts between
       | people. Some want individual freedom to manage branches in
       | whatever way (and these people are usually very open to other
       | people managing branches in another way), but some people are
       | against this freedom and thinks branches should be managed
       | centrally by an authority (such people usually have a problem
       | working on their own).
        
       | guytv wrote:
       | I just let claude do all conflict resolution for me. code
       | conflicts are a solved problem.
        
       | mpalmer wrote:
       | This sounds more like the _present_ of version control in the
       | form of Jujutsu, which already supports 3-way merges and history-
       | preserving rebases, and does so with data structures that are
       | trivially representable in a standard git repo.
       | 
       | > What it is is a proof that CRDT-based version control can
       | handle the hard UX problems and come out with better answers than
       | the tools we're all using today -- and a coherent design for
       | building the real thing.
       | 
       | No such thing is "proven". You have not proven superiority to the
       | state of the art with 400 lines of Python.
       | 
       | The LLM you used to draft this blog post is making your solution
       | out to be far more than it is at this point.
        
       | gigatexal wrote:
       | how are CRDTs magic wrt to merges and conflicts?
       | 
       | im happy to see new entrants into the space. I think I'm a git
       | beginner+. I know enough to be productive and am no longer
       | fearful of it... and I even train up my coworkers on it and help
       | them out of binds... but I am not an expert by any means and
       | still sometimes resort to radical things to get me through some
       | problem I've put myself into.
        
       | metmac wrote:
       | https://loro.dev/
       | 
       | Relevant. Loro a lovely CRDT library, explored implementing VCS
       | semantics with CRDTs.
        
       | m12k wrote:
       | I used to think the future of version control was semantic: E.g.
       | I renamed a method, while someone else concurrently added another
       | call to that (now differently named) method. Git doesn't catch
       | this, nor would this new system. The solution seems obvious to a
       | human: Use the new name at the new call-site too. But it requires
       | operating at the level of the semantic meaning of a change, and
       | not just the dumb textual changes. I used to think this would
       | require a new version control system that encodes the semantics
       | of the changes in the commits, in order to have them available at
       | merge-time. But these days, it seems much more realistic to stick
       | to git, but loop in LLMs when merging, to re-create the semantics
       | from the textual changes.
        
         | bilekas wrote:
         | This is more than just a version control though, they only
         | thing any VC uses that's important is the diff and the
         | timestamps, you would be adding in project context awareness
         | which is a whole other thing.
         | 
         | I'm sure there are smarter people than me who could create some
         | hooks to automagically update those references on merge/rebase
         | though. Not sure I would pay a whole LLM each time personally.
        
         | WolfeReader wrote:
         | Darcs did this decades ago with the "replace" command. It's not
         | a legitimate semantic replacement, though - it's more just
         | telling your VCS to do a find/replace.
        
           | gnufx wrote:
           | As far as I remember, that's just because only the
           | find/replace was implemented, and it could have more
           | sophisticated (semantic?) features.
        
         | cush wrote:
         | > I renamed a method, while someone else concurrently added
         | another call to that
         | 
         | This is the most common use case for any compiler or linter
        
       | blueplanet200 wrote:
       | Reminds me of this article from way back, "A look back: Bram
       | Cohen vs Linus Torvalds"
       | 
       | Of significance here because the resolution strategy from merges
       | was deeply at the disagreement between Bram and Linus.
       | 
       | https://web.archive.org/web/20110728005409/http://www.wincen...
        
         | jancsika wrote:
         | It's worth reflecting on just how many VCS data (or pain)
         | points Linus had ingested right before writing git. Probably
         | more than anyone in FOSS outside of maybe a few Debian devs.
         | Add to that his experience successfully using Bitkeeper prior
         | to that and you can easily see why git is where it is in 2026.
         | 
         | Given a large enough amount of data/pain, designing/optimizing
         | to attack _specific, known pain points_ always beats trying to
         | solving a more general problem elegantly. I mean, kudos to
         | whoever decided Zoom clients with shoddy connections should
         | buffer then race back to realtime at 1.x - 2x speed (can 't
         | remember exactly how fast it goes-- perhaps it's dynamic?). One
         | could come up with 1000 toy examples of where that breaks
         | (music lesson, drama class, etc.), or just implement it and
         | save a gazillion people gazillion hours of repeating themselves
         | in boring meetings.
         | 
         | Edit: clarification
        
       | tinfoilcondom wrote:
       | Why are some projects like "artifact" marked Dead here while
       | others like "fossil" are promoted in the comments?
       | 
       | What counts as advertise vs spam? They seem like nearly identical
       | posts and both projects really exist, separate authors.
       | 
       | Why are random posts marked Dead on this platform? Seems like
       | outright censorship
        
       | itsnexis wrote:
       | The insight about rebase is underappreciated. The reason rebase
       | is "considered harmful" in many teams isn't just that it rewrites
       | history -- it's that it makes history a lie that eventually
       | collapses under its own weight in large teams. The CRDT weave
       | approach is clever because it separates two things that git
       | conflates: the logical order you want the commits to appear in
       | (narrative history) vs. the actual causal order things happened
       | (real history). Keeping both is strictly better. The conflict
       | marker improvement alone would be worth the migration cost for
       | many teams. Two opaque blobs with no attribution is genuinely one
       | of the worst UX failures in developer tooling.
        
         | cweagans wrote:
         | > it makes history a lie that eventually collapses under its
         | own weight in large teams
         | 
         | Can you please elaborate on this? I've seen this argument from
         | others as well, but nobody has ever been able to articulate
         | what that actually looks like and why rebasing branches
         | specifically is to blame.
         | 
         | My perspective: whatever happens to the commit history on your
         | non-`main` branch is your business. I don't care about the
         | specifics until your work is merged into a shared branch that
         | we all understand to be the canonical representation of the
         | software we're working on.
        
           | idoubtit wrote:
           | I'm not the GP, but I've seen "rebase lies" in the wild.
           | 
           | Suppose a file contains a list of unique strings, one by
           | line. A commit on a feature branch adds an element to the
           | list. Later on, the branch is rebased on the main branch and
           | pushed.
           | 
           | But the main branch had added the same element at another
           | position in the list. Since there was a wide gap between the
           | two positions, there was no conflict in Git's rebase. So the
           | commit in the feature branch breaks the unicity constraint of
           | the list.
           | 
           | For someone that pulled the feature branch, the commit seems
           | stupid. But initial commit was fine, and the final (rebased)
           | commit is a lie: nobody created a duplicate item.
        
             | cweagans wrote:
             | Thanks for that. I'm definitely familiar with that kind of
             | situation, but what I'm not seeing is how that leads to
             | history "collapsing under its own weight" in larger teams.
             | That seems like a relatively straightforward rebase error
             | that is easily corrected. (Also, if it is important for
             | that list to only include unique items and you were able to
             | merge it anyway, maybe that also reveals a gap in the test
             | suite?)
        
           | cxr wrote:
           | > Can you please elaborate on this?
           | 
           | You're replying to an LLM-powered comment generator.
        
       | brahimmami wrote:
       | Brahim 1462163579
        
       | cush wrote:
       | The single trivial example is not convincing
        
       | r3c0nc1l3r wrote:
       | This is a cool idea!
       | 
       | These days, I think that all new version control solutions now
       | have to be examined in the light of how well they work with with
       | coding agents.
       | 
       | In that light, the CRDT merging here is interesting, as it allows
       | history preservation in scenarios that would otherwise be
       | destructive. This way, agents can use worktrees with much less
       | hassle as squash, rebase, merge become more straightforward.
        
       | Koshkin wrote:
       | What's currently missing from the automatic conflict resolution
       | is intelligence. The AI doing merges _is_ the future.
        
       ___________________________________________________________________
       (page generated 2026-03-23 23:01 UTC)