diff3

package module
v0.0.0-...-3b16698 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2026 License: MIT Imports: 7 Imported by: 5

README

diff3

Package diff3 implements a three-way merge algorithm Original version in Javascript by Bryan Housel @bhousel: https://github.com/bhousel/node-diff3, which in turn is based on project Synchrotron, created by Tony Garnock-Jones. For more detail please visit: http://homepages.kcbbs.gen.nz/tonyg/projects/synchrotron.html https://github.com/tonyg/synchrotron

Ported to go by Javier Peletier @jpeletier

How to use

Import the package and call Merge:

Merge(a, o, b io.Reader, detailed bool, labelA string, labelB string) (*MergeResult, error)

Where:

  • a and b are the current and incoming versions of content
  • o is the common ancestor
  • detailed specifies whether you want the merge conflicts to be detailed.
  • labelA and labelB indicate a label to mark conflicts with, usually the branch names.

Returns a MergeResult that includes a flag indicating whether there were conflicts or not and a io.Reader stream with the result.

For callers that already have line or token slices, call the generic API directly:

result := diff3.Diff3Merge(aLines, oLines, bLines, true)

The generic type parameter is inferred for common calls. If inference is not possible, specify it explicitly:

result := diff3.Diff3Merge[string](aLines, oLines, bLines, true)

Diff3Merge accepts any comparable element type, so callers can merge token slices as well as string lines.

Algorithm Selection

The default algorithm remains the original Hunt-McIlroy LCS implementation.

Use MergeWithOptions or Diff3MergeWithOptions to opt into Myers diff:

result, err := diff3.MergeWithOptions(a, o, b, diff3.MergeOptions{
	Algorithm:             diff3.DiffAlgorithmMyers,
	ExcludeFalseConflicts: true,
	Detailed:              true,
	LabelA:                "current",
	LabelB:                "incoming",
})

For slices:

result := diff3.Diff3MergeWithOptions(aLines, oLines, bLines, diff3.MergeOptions{
	Algorithm:             diff3.DiffAlgorithmMyers,
	ExcludeFalseConflicts: true,
})

Breaking API Changes

Diff3Merge, Diff3MergeResult, and Conflict are now generic.

Before:

var result []*diff3.Diff3MergeResult
var conflict *diff3.Conflict

After:

var result []*diff3.Diff3MergeResult[string]
var conflict *diff3.Conflict[string]

The fields on Diff3MergeResult and Conflict are now exported and inspectable:

for _, item := range result {
	if item.Ok != nil {
		// merged non-conflict block
	}

	if item.Conflict != nil {
		_ = item.Conflict.A
		_ = item.Conflict.O
		_ = item.Conflict.B
		_ = item.Conflict.AIndex
		_ = item.Conflict.OIndex
		_ = item.Conflict.BIndex
	}
}

Direct calls to Diff3Merge with []string usually continue to compile through type inference. Code that names Diff3MergeResult or Conflict must add the type argument, usually [string].

Attribution

The generic API, exported merge result fields, Myers diff implementation, and parallel diff computation are based on work by Kyungmin Bae and Devsisters in devsisters/go-diff3.

Documentation

Overview

Package diff3 implements a three-way merge algorithm Original version in Javascript by Bryan Housel @bhousel: https://github.com/bhousel/node-diff3, which in turn is based on project Synchrotron, created by Tony Garnock-Jones. For more detail please visit: http://homepages.kcbbs.gen.nz/tonyg/projects/synchrotron.html https://github.com/tonyg/synchrotron

Ported to go by Javier Peletier @jpeletier

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Conflict

type Conflict[T any] struct {
	A      []T
	AIndex int
	O      []T
	OIndex int
	B      []T
	BIndex int
}

Conflict describes a merge conflict.

type Diff3MergeResult

type Diff3MergeResult[T any] struct {
	Ok       []T
	Conflict *Conflict[T]
}

Diff3MergeResult describes a merge result.

func Diff3Merge

func Diff3Merge[T comparable](a, o, b []T, excludeFalseConflicts bool) []*Diff3MergeResult[T]

Diff3Merge applies the output of diff3MergeIndices to actually construct the merged file; the returned result alternates between 'ok' and 'conflict' blocks.

func Diff3MergeWithOptions

func Diff3MergeWithOptions[T comparable](a, o, b []T, opts MergeOptions) []*Diff3MergeResult[T]

type DiffAlgorithm

type DiffAlgorithm int
const (
	DiffAlgorithmLCS DiffAlgorithm = iota
	DiffAlgorithmMyers
)

type DiffResult

type DiffResult[T any] struct {
	Common []T
	File1  []T
	File2  []T
}

func DiffComm

func DiffComm[T comparable](file1, file2 []T) []*DiffResult[T]

We apply the LCS to build a 'comm'-style picture of the differences between file1 and file2.

type MergeOptions

type MergeOptions struct {
	Algorithm             DiffAlgorithm
	ExcludeFalseConflicts bool
	Detailed              bool
	LabelA                string
	LabelB                string
}

type MergeResult

type MergeResult struct {
	Conflicts bool      // Conflict indicates if there is any merge conflict
	Result    io.Reader // returns a reader that contains the merge result
}

MergeResult describes a merge result

func Merge

func Merge(a, o, b io.Reader, detailed bool, labelA string, labelB string) (*MergeResult, error)

Merge takes three streams and returns the merged result

func MergeWithOptions

func MergeWithOptions(a, o, b io.Reader, opts MergeOptions) (*MergeResult, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL