Subject: [NOTES 02/11] First-class conflicts in Git?

From: Taylor Blau <[email-masked]>
Date: Mon, 6 Oct 2025 15:18:22 -0400

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