# What Merge Algorithm Is Used for Zakirullin Files Edits?

> Discover the merge algorithm for Zakirullin Files edits. It uses a dynamic programming LCS approach with custom Markdown header post-processing for efficient version control.

- Repository: [Artem Zakirullin/files.md](https://github.com/zakirullin/files.md)
- Tags: internals
- Published: 2026-05-21

---

**TLDR:** The Zakirullin Files merge algorithm relies on a classic Longest Common Subsequence (LCS) implementation using dynamic programming, supplemented by specialized post-processing for Markdown journal headers.

The [`zakirullin/files.md`](https://github.com/zakirullin/files.md/blob/main/zakirullin/files.md) repository implements a deterministic, line-based merging strategy for collaborative text editing. At its core, the merge algorithm processes conflicting versions of files by computing the longest common subsequence of line arrays, ensuring order-preserving convergent edits across distributed clients according to the zakirullin/files.md source code.

## How the LCS Merge Algorithm Works

The implementation in [`server/sync/merge.go`](https://github.com/zakirullin/files.md/blob/main/server/sync/merge.go) follows a three-phase approach to reconcile divergent file versions.

### Line Splitting and Comparison

The algorithm first normalizes inputs by splitting both text versions on line breaks (`\n`). This transforms the merge problem into finding the longest common subsequence between two string slices rather than character arrays, as implemented in zakirullin/files.md.

### Dynamic Programming Table Construction

The core logic builds a two-dimensional matrix `lcsLength` that stores the length of the longest common prefix for every pair of line indices. According to the source code in [`server/sync/merge.go`](https://github.com/zakirullin/files.md/blob/main/server/sync/merge.go), the recurrence relation follows the classic LCS dynamic programming approach:

```go
if lines1[i-1] == lines2[j-1] {
    lcsLength[i][j] = lcsLength[i-1][j-1] + 1
} else {
    lcsLength[i][j] = max(lcsLength[i-1][j], lcsLength[i][j-1])
}

```

This table construction runs in `O(n*m)` time complexity where `n` and `m` represent the line counts of the input documents.

### Backtracking and Reconstruction

After populating the DP table, a recursive `backtrack` function traverses the matrix from the bottom-right corner toward the origin. The reconstruction process preserves lines belonging to the LCS exactly once and appends unique lines from either version in their original order, returning a deterministic merged line slice suitable for journal files and configuration snippets.

## Special Handling for Journal Headers

Beyond the generic text merge, [`server/sync/merge.go`](https://github.com/zakirullin/files.md/blob/main/server/sync/merge.go) contains specialized logic for Markdown journal headers through the `mergeEmojisInJournalHeaders` function.

### Emoji Deduplication and Concatenation

The post-processing stage groups consecutive Markdown headers using the `groupConsecutiveHeaders` helper, with additional support from a `unique` utility function. For headers sharing the same date and title but differing emojis, the algorithm deduplicates identical emoji characters, concatenates unique emojis into a single header line, and reinserts the cleaned header into the final output.

As demonstrated in [`server/sync/merge_test.go`](https://github.com/zakirullin/files.md/blob/main/server/sync/merge_test.go), this handles scenarios like:

```go
// From TestMergeHeaders
headers := []string{
    "#### 23 May, Friday 🤸‍♂️",

    "#### 23 May, Friday 🍽💪",

    "#### 23 May, Friday 💧",

}
merged := mergeEmojisInJournalHeaders(headers)
// merged == []string{"#### 23 May, Friday 🤸‍♂️🍽💪💧"}

```

## Practical Implementation Example

The `Merge` function exported by the sync package provides a straightforward interface for string reconciliation. The following example demonstrates both plain text merging and journal header processing:

```go
package main

import (
    "fmt"
    "github.com/zakirullin/files.md/server/sync"
)

func main() {
    // Simple line-based merge
    a := "line 1\nline 2"
    b := "line 1\nline 2\nline 3\nline 4"
    fmt.Println(sync.Merge(a, b))
    // → line 1
    //   line 2
    //   line 3
    //   line 4

    // Journal header merge (emojis are deduped and combined)
    hdrA := "#### 23 May, Friday 🤸‍"

    hdrB := "#### 23 May, Friday 🍽💪"

    merged := sync.Merge(hdrA, hdrB)
    fmt.Println(merged)
    // → #### 23 May, Friday 🤸‍🍽💪

}

```

## Summary

- The Zakirullin Files merge algorithm uses a **Longest Common Subsequence (LCS)** approach implemented with dynamic programming in [`server/sync/merge.go`](https://github.com/zakirullin/files.md/blob/main/server/sync/merge.go).
- A **2-D DP table** (`lcsLength`) tracks common line sequences using the recurrence relation comparing `lines1[i-1]` and `lines2[j-1]`.
- **Backtracking** reconstructs the merged output by traversing the matrix from bottom-right to top-left.
- **Journal-specific post-processing** via `mergeEmojisInJournalHeaders` handles Markdown headers by deduplicating and concatenating emojis across consecutive entries.
- The implementation is **deterministic** and **order-preserving**, making it suitable for plain-text documents, configuration files, and journal formats.

## Frequently Asked Questions

### What type of merge algorithm does Zakirullin Files use?

The repository implements a classic **Longest Common Subsequence (LCS)** algorithm using dynamic programming. This approach finds the optimal alignment between two line-based text versions, preserving the maximum common content while deterministically ordering unique changes from both inputs.

### How does the algorithm handle Markdown headers with emojis?

After the generic LCS merge, the `mergeEmojisInJournalHeaders` function groups consecutive Markdown headers that share the same text content. It extracts all unique emoji characters from these grouped headers, concatenates them, and reconstructs a single header line containing the combined emoji set, preventing duplicate date headers while preserving mood indicators from multiple editing sessions.

### Where is the merge logic implemented in the codebase?

The primary implementation resides in **[`server/sync/merge.go`](https://github.com/zakirullin/files.md/blob/main/server/sync/merge.go)**, which contains the `Merge` function, the `backtrack` reconstruction logic, and the header-specific post-processors. Comprehensive unit tests defining expected behavior for edge cases, plain text, and emoji headers are located in **[`server/sync/merge_test.go`](https://github.com/zakirullin/files.md/blob/main/server/sync/merge_test.go)**.

### Is the Zakirullin Files merge algorithm deterministic?

Yes, the algorithm produces deterministic output. The dynamic programming approach yields a unique LCS length matrix, and the backtracking traversal follows a consistent path when values are equal. This ensures that given the same two input versions, the merge result is identical across all client instances, which is critical for distributed consistency in collaborative editing.