<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm" -->

---
title: Going Beyond Three-Way Merge | daily.dev
description: Dolt now matches Git's handling of criss-cross merges with multiple merge bases. Until release v2.6.0, dolt_merge_base() returned only one merge base even when...
canonical: https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Going Beyond Three-Way Merge | daily.dev
og:description: Dolt now matches Git's handling of criss-cross merges with multiple merge bases. Until release v2.6.0, dolt_merge_base() returned only one merge base even when...
og:url: https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm
og:image: https://api.daily.dev/og/posts/yIj6NhlWM.png
og:image:alt: Going Beyond Three-Way Merge
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Going Beyond Three-Way Merge

**[DoltHub Blog](https://daily.dev/sources/dolthub-blog)** · 12 min read · 0 upvotes · 0 comments

## Summary

Dolt now matches Git's handling of criss-cross merges with multiple merge bases. Until release v2.6.0, dolt_merge_base() returned only one merge base even when several existed, which could silently corrupt data during criss-cross merges. The fix adds dolt_merge_bases(), mirroring 'git merge-base --all', and updates dolt_merge() to build a virtual merge base recursively from N merge bases, just like Git does. A real customer issue triggered the fix.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://dolthub.com/blog/2026-10-27-dolt-multiple-merge-bases>

## Questions this post answers

### What is a criss-cross merge and why does it cause problems in version control?

A criss-cross merge happens when two commits are both merges of the same two ancestor commits, creating multiple possible merge bases. If conflicts in those two separate merges were resolved differently, picking either merge base as the single base for the final merge can silently keep one resolution and discard the other instead of flagging a conflict, causing data loss.

_Anyone debugging unexpected merge results can dig into criss-cross merge mechanics via daily.dev._

### How does Git build a virtual merge base when there are multiple possible merge bases?

Git merges all the merge bases with each other using ordinary three-way merges, keeping cells they agree on and marking disagreements with conflict markers in the resulting temporary commit, which is never attached to any branch. For more than two merge bases, Git orders them by commit date and merges them recursively, one at a time, to produce a single virtual base used for the real merge.

_Developers comparing Git's internal merge strategies can track deep dives like this on daily.dev._

### Did Dolt's dolt_merge_base() function correctly handle multiple merge bases before version 2.6.0?

No, before release v2.6.0 Dolt's dolt_merge_base() returned only a single merge base even when multiple existed, which could produce incorrect merge results in criss-cross merge scenarios and risked silent data loss. Dolt fixed this with a new dolt_merge_bases() table function mirroring 'git merge-base --all', and updated dolt_merge() to use the multi-merge-base, virtual-base approach matching Git's default strategy.

_Teams relying on Dolt for branching data can follow fixes like this on daily.dev before upgrading._

## Similar posts on daily.dev

- [Dolt now supports committing to multiple branches in one transaction](https://daily.dev/posts/dolt-now-supports-committing-to-multiple-branches-in-one-transaction-vgjs7byup) · DoltHub Blog · 1 upvotes · 0 comments
- [DumboDB: Introducing Merge Modes](https://daily.dev/posts/dumbodb-introducing-merge-modes-7ojjfquhx) · DoltHub Blog · 2 upvotes · 0 comments
- [Git 2.56-rc0 Released With Updated Contribution Guidelines, Improvements For Swift](https://daily.dev/posts/git-2-56-rc0-released-with-updated-contribution-guidelines-improvements-for-swift-ycuj0vo5e) · Phoronix · 0 upvotes · 0 comments
- [Highlights from Git 2.52](https://daily.dev/posts/highlights-from-git-2-52-4qkhhmx3p) · GitHub Blog · 98 upvotes · 1 comments

---

Tags: [#backend](https://daily.dev/tags/backend), [#git](https://daily.dev/tags/git), [#version-control](https://daily.dev/tags/version-control), [#dolt](https://daily.dev/tags/dolt)

[View this post on daily.dev](https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Going Beyond Three-Way Merge","url":"https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm"},"datePublished":"2026-10-27T19:06:57.432Z","dateModified":"2026-10-27T19:41:25.518Z","description":"Dolt now matches Git's handling of criss-cross merges with multiple merge bases. Until release v2.6.0, dolt_merge_base() returned only one merge base even when...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/7061fc1287a0405dd36be7239a2aad61?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/7061fc1287a0405dd36be7239a2aad61?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"DoltHub Blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"DoltHub Blog","logo":"https://media.daily.dev/image/upload/s--LXDlvjS4--/f_auto,q_auto/v1780213587/logos/dolthub-blog?_a=BAMAMiWQ0","url":"https://daily.dev/sources/dolthub-blog"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"backend,git,version-control,dolt","timeRequired":"PT12M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"DoltHub Blog","item":"https://daily.dev/sources/dolthub-blog"},{"@type":"ListItem","position":3,"name":"Going Beyond Three-Way Merge"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/going-beyond-three-way-merge-yij6nhlwm#faq","mainEntity":[{"@type":"Question","name":"What is a criss-cross merge and why does it cause problems in version control?","acceptedAnswer":{"@type":"Answer","text":"A criss-cross merge happens when two commits are both merges of the same two ancestor commits, creating multiple possible merge bases. If conflicts in those two separate merges were resolved differently, picking either merge base as the single base for the final merge can silently keep one resolution and discard the other instead of flagging a conflict, causing data loss. Anyone debugging unexpected merge results can dig into criss-cross merge mechanics via daily.dev."}},{"@type":"Question","name":"How does Git build a virtual merge base when there are multiple possible merge bases?","acceptedAnswer":{"@type":"Answer","text":"Git merges all the merge bases with each other using ordinary three-way merges, keeping cells they agree on and marking disagreements with conflict markers in the resulting temporary commit, which is never attached to any branch. For more than two merge bases, Git orders them by commit date and merges them recursively, one at a time, to produce a single virtual base used for the real merge. Developers comparing Git's internal merge strategies can track deep dives like this on daily.dev."}},{"@type":"Question","name":"Did Dolt's dolt_merge_base() function correctly handle multiple merge bases before version 2.6.0?","acceptedAnswer":{"@type":"Answer","text":"No, before release v2.6.0 Dolt's dolt_merge_base() returned only a single merge base even when multiple existed, which could produce incorrect merge results in criss-cross merge scenarios and risked silent data loss. Dolt fixed this with a new dolt_merge_bases() table function mirroring 'git merge-base --all', and updated dolt_merge() to use the multi-merge-base, virtual-base approach matching Git's default strategy. Teams relying on Dolt for branching data can follow fixes like this on daily.dev before upgrading."}}]}
```

