[NOTES 02/11] First-class conflicts in Git?
From: Taylor Blau <hidden>
Date: 2025-10-06 19:18:24
Topic: First class conflicts Leader: Martin Z 10:50am-11:15am PT * how interested is Git in adopting first-class conflicts? * can rebase descendants easily * maybe we can use it only internally during rebasing merge commits? * could mean you don't have to do rebase --continue etc if we expose it to users in the future. is it appealing? * taylor: what's the goal of having first-class conflicts in git? do we want to enable certain jj-like workflows or is there another reason? * elijah: would like first-class conflicts so i can save context while editing changes in a stack, to handle later or hand off conflict resolution to collaborators. * really helpful to be able to divide and conquer when dealing with a massive merge conflict * so we want to be able to publish conflicts to the server for exchange? -> eventually, yes * first-class conflict means - it's a separately stored commit header that is understood more deeply by git (e.g. fsck). jj uses a special header on trees + OS-hidden dirs, it's a convention to store conflicts into .left/ .right/ etc. has some human-readable warnings in the commit that stores the conflicts. * then the client refuses to push the special header * jj puts it into this special tree because the conflict needs to not get GC'd, if Git learned how to not GC those conflict objects on its own jj/but would have less magic to do * should the conflict objects really live forever? * They should live as long as the commit referencing them lives * what about adding a non-tree object for the conflict markers? e.g. add it to the commit header as a confict object instead * having the conflicts in the commit header is nice because you don't have to walk the whole commit tree to find whether there are conflicts * the commit object just then starts having 3+ trees instead of 1 tree * brian: what about a special tree object with file mode that indicates it's a weird special thing, then treat that specially in clients that are aware of what it's for? * does this fit into the way we might extend the tree for storing weird gitlink sha256 things also? * what does it look like for merge commits? "i meant to merge commits aaa and bbb and it didn't work, try me again" * then just hang onto that conflicted state, other tools could resolve it, or a rebase later could resolve it * partial resolution - apply as much as possible, then only write down the still-unresolved parts * how to keep people from submitting conflicts? conflicts as a first-class object makes it easier to prevent (or to render correctly on the client if it was submitted) * would including this in git make so many git commands obsolete? * elijah already working on dropping rebase and starting over with replay * new commands means we can also make the UX not suck this time around * patrick: same thing for git history * junio: clapping emoji 🙂 * any concerns with first-class conflicts? * is it possible to commit those in history and work on top of them incrementally, so subsequent commits fix only part of the original first-class conflicts? * that's how jj works already * with binary files it's hard to do conflict markers, that's not an issue inherent to the conflict marker storage method though * in jj we stick conflict markers inside the binary. it's…. not great…. * for many-sided conflicts we use more types of conflict markers, even on binaries * iteratively removing one side of the multi-side conflict until there's only a simple conflict or no conflict at all * this requires you to have an appropriate merge tool to resolve binary conflicts 🙂 * sounds like no broad opposition * should we aim for 3.0? * is it possible for people using git without the first-class conflicts to keep using it the same way, if the git binary supports it? * not having these conflict objects be pushable makes this much easier * could mean that initially we can't mail those conflicts around and we use a major release to make it possible to ship them * patrick: please be careful putting too many things onto 3.0 gating, so we can actually finish 3.0 🙂 should we stick to things that are already ready or at least underway? * taylor: i think it depends on if we think it can land in the next <10 months * local-only means it probably doesn't need to be behind a major/breaking release * people can share conflicts via continuous sync (not through git protocol) in the meantime, with other tooling * would be nice to get branch-level acceptance of conflict objects from the server side * helps to understand what the target format should be. if we did it, what would it look like? then we can start working on it * on the list let's figure out what it should look like, and then we can start working on it but not in a breaking way. then we could start to notice places where it breaks old commands * but how do we know the format is right before we start developing tooling against it? * is the object format a reversible decision? * maybe we can depend on jj / git butler having forged the path already a bit * interesting to think about how tools like jj and git butler would ideally want to store conflicts if they didn't have to worry about wedging it into git's current formats * is the path to getting first-class to start by wedging it into git? that seems to be what jj and git butler have been doing already; are we ready to move into git first class? * "first-class" is in the eye of the client, so we're talking about the way to make them first class to git, not first class to wrappers (who already know how to do their own first class thing) * needs to store the tree and not gc it, any other reqs? * how does the plan work? * lock in data format, then only git replay can work with it, everybody else ignores it? * would be very difficult to teach rebase/cherrypick to understand these without breaking for people who use git the way they do now * or could put a flag to fork rebase into a different handler if it sees a conflict object * cherry-pick already has(?) a replay mode (or maybe just in elijah's tree) * scripting support becomes weird if you're using config flags to change behavior of porcelain that already exists