Hacker News new | ask | show | jobs
by oftenwrong 1795 days ago
For user changes, a solution based on OT/CRDT may be appropriate.

For code, you need merge conflicts. Let me put it like this: Do concurrent edits in google docs always produce a valid and correct paragraph, with no grammatical errors, and that communicates the proper thoughts?

1 comments

If we need merge conflicts that must be manually resolved, how can this product being discussed exist?

If merge conflicts can be automatically resolved, why aren't we using a system that does operates like that under the hood rather than needing a product like this bolted on?

The product being discussed here doesn't solve the issue of merge conflicts itself, but rather of eventual consistency. Merge conflicts is only a part of it, and there are some heuristics that can be used to reduce those, but eventually require manual review. Perhaps with Github Copilot this can improve?

An example of the problem we are describing is explained here: https://blog.mergequeue.com/managing-github-merges-for-high-...

There are ways to resolve merge conflicts automatically in some cases given some assumptions, but there is no way to resolve any given merge conflict without a system that can create a correct program. I won't bore you with the formal proof for this (especially since I have no idea how to construct such a proof). Consider that some merge conflicts require new code to be written to resolve them.

For example, here's an original program:

    if(foo()) {
      send_money_to_oftenwrong()
    }
and here's a change we would like to merge:

    if(bar()) {
      send_money_to_oftenwrong()
    }
and here's a concurrent change we would like to merge:

    if(baz()) {
      send_money_to_oftenwrong()
    }
How do you produce the correct program from these conflicting changes?

---

Also for example, an unsophisticated and unsound method for automatically resolving some merge conflicts:

1. Assume that if the build and tests succeed, the program is correct. (This is the most important bit)

2. Accept all non-conflicting changes.

3. For conflicting changes, accept one side of the conflict.

4. Build and test the result. If it succeeds, merge it.

5. Otherwise, attempt the same with the other side of the conflict. If it succeeds, merge it.

6. Otherwise, it cannot be merged automatically by this method.

Note that this approach could also apply to a CRDT-based merge.

I'm on a medium sized team so this might not be possible for everyone. The way I resolve this in my Trunk-Based source control system(so we heavily use Feature Flags) is to just never merge.

Every person who is to check-in code is to first stash their changes, pull all code, then pop the stash and deal with any conflicts locally, do the relevant testing, then check-in. The entire repo is checkin 1 -> checkin 2 -> checkin 3 -> etc..

When viewed in this light it is no different than if you had pulled the baz() code before you started editing anything. Would you have changed it to bar() or not?