---
title: "Understanding zealous diff3 style in Git conflicts"
description: "Master conflicts resolving by switching from 'merge' to zealous diff3 also known as 'zdiff3' for conflicts markers in Git version control system."
canonical_url: "https://new.neg4n.dev/blog/understanding-zealous-diff3-style-git-conflict-markers"
md_url: "https://new.neg4n.dev/blog/understanding-zealous-diff3-style-git-conflict-markers.md"
section: "blog"
date_published: "2025-05-31T07:15:23.000Z"
last_updated: "2026-05-25T03:03:14.004Z"
reading_time: "8 min read"
tags: ["git","vcs","cli","diff","merge","productivity"]
---

# Understanding zealous diff3 style in Git conflicts

When collaborating on code with others or merging branches in **Git**, conflicts are inevitable. A common tool to resolve these conflicts is built-in markers mechanism. Although `merge` style of conflict markers became the well-known industry standard, there is still room to improve the experience of using the version control system in this area. This article aims to explain what `zdiff3` is and how it can be applied to conflict markers and highlight the algorithm significance.

## Branching, merging and why conflicts even occur

In **Git**, development most of the times happens in branches. A branch in **Git** is essentially a movable pointer to one of the commits. The default branch in **Git** is usually called `main`, `trunk` or `master` - developers create new branches for features, bug fixes, or experiments. These branches allow developers to work on the code independently from the main line of development.

When the work on a branch is complete, it is merged back e.g. into the `main` branch *(it does not have to be the default branch, often feature branches are merged into other feature branches)*. **Git** attempts to automatically merge the changes by combining the snapshots pointing to the specific branch pointers. If the changes in the two branches do not overlap, **Git** can usually merge them automatically.

In other cases **Git** will raise a conflict.

### Common scenarios for merge conflicts

- **Editing the same line**: Two branches have made different changes to the same line of a file.
- **One branch edits a file while another deletes it**: One branch makes changes to a file, while another branch deletes that same file.
- **Concurrent file renaming**: Two branches rename the same file differently or make changes to a file that one of the branches has renamed.

## What is Git's zealous diff3 merge conflicts style?

The `zdiff3` conflict marker is an option for a merge conflict markers in **Git** that provides way more context than default `merge` style at the same time being enhanced version of `diff3`. It shows the common ancestor's version in addition to the two conflicting changes, offering a three-way comparison - just like `diff3`.

### Comparison of zdiff3 vs diff3

Unlike the `diff3`, zealous one tries to resolve as many conflicts as possible by itself. It is a bit more aggressive in its approach - which results in less manual work for the developer during the process.

### Installation of new conflict style

Actually, the question *"how to install zdiff3"* is quite wrong - it is already built into the **Git** without any need for installation. The `zdiff3` conflict markers are activated by setting the merge conflict style in the configuration via CLI:

```bash
git config --global merge.conflictstyle zdiff3
```

... or by setting it directly in the `.gitconfig` file:

```txt
...
[merge]
  conflictstyle = zdiff3
...
```

> [!TIP]
> For troubleshooting e.g. why there's error `error: unknown style 'zdiff3' given for 'merge.conflictstyle'` or why changes in the configuration do not take effect, see the [Troubleshooting common zdiff3 and diff3 configuration issues](#troubleshooting-common-zdiff3-and-diff3-configuration-issues) section.

### Structure of zdiff3 and diff3 conflict markers

A `zdiff3` and `diff3` conflict marker styles divide the conflicting area into three sections:

1. **Local Changes** (HEAD): Changes that are present in the current branch.
2. **Base Changes** (Ancestor): The common ancestor's version of this part of the file.
3. **Incoming Changes** (MERGE\_HEAD): Changes that are present in the branch being merged into the current one.

The sections are separated by different markers:

- `<<<<<<< HEAD` marks the beginning of the local changes.
- `||||||| merged common ancestors` marks the beginning of the base changes.
- `=======` separates the local changes from the incoming changes.
- `>>>>>>> MERGE_HEAD` marks the end of the incoming changes.

### Understanding the difference between all mentioned conflict styles

Let's start from the default `merge` style of conflict markers. It is the most common and widely used style. It is simple and easy to understand. It shows only the local changes and the incoming changes, being a two-way comparison.

![Drawing of merge Git conflict markers](https://assets.neg4n.dev/git-conflict-merge-kPRor8hHnYtlOq3i2mf7IYcSzome1Z-light-v2.svg)

*Reference drawing explaining how does the merge conflicts style look like*

Frankly speaking - it is not enough to resolve the conflict in a complex scenario. It is not enough to understand the context of the changes and the evolution of the code. This is where `diff3` and `zdiff3` come into play.

### Reference example of a diff3 style conflict

![Drawing of diff3 Git conflict markers](https://assets.neg4n.dev/git-conflict-diff3-YQZbds85rt6WMkpla1DdjbeZrGPVzV-light-v2.svg)

*Reference drawing explaining how does the diff3 conflicts style look like*

Unlike previous style and apart from the common ancestor section, the `diff3` does not try to aggresively resolve the conflicts by itself, which is easy spottable on the embedded drawing. The developer gets full set of information it is up to him to decide which changes to keep and which to discard.

### Reference example of a zdiff3 style conflict

![Drawing of zdiff3 Git conflict markers](https://assets.neg4n.dev/git-conflict-zdiff3-2uyoOrYo0Y5Vi8xONpY12Efk3LKDCU-light-v2.svg)

*Reference drawing explaining how does the zealous diff (aka zdiff3) conflicts style look like*

And here comes the `zdiff3` style. As the name says - it is zealous version of a `diff3`. The behavior can be summed up as an `merge` + `diff3` - in this style both aggressive resolving and common ancestor features are present.

Personally I find it the most useful, straightforward and productive style of conflict markers. It is the most informative *(but not overwhelming)* information-wise, since changes that are the same between local and incoming are moved out of conflict markers leaving clean ground for analyzing the code.

### Explore the differences in practice

If you want to play with the examples from the drawings, create a new directory and use the following commands to create a conflict and see how it looks in different styles:

```bash
git init \
  && git branch -m main \
  && echo -e "Foo\nHello" > file.txt \
  && git add file.txt \
  && git commit -m "a" \
  && git branch new-branch \
  && git switch new-branch \
  && echo -e "Bar\nFarwell" > file.txt \
  && git add file.txt \
  && git commit -m "b" \
  && git switch main \
  && echo -e "Bar\nHello" > file.txt \
  && git add file.txt \
  && git commit -m "c" \
  && git merge new-branch
```

> [!NOTE]
> Assuming, you've started exploring from `zdiff3` you can create another directory and change the `merge.conflictstyle` to `merge` and `diff3` in the meantime and compare the outcome. The *"ready-to-paste"* command is aligned with the changes and conflicts presented in this article's drawings so it should be very straightforward to understand the concept visually.

## Troubleshooting common zdiff3 and diff3 configuration issues

When setting up `zdiff3` or `diff3` conflict styles, you might encounter some issues. These problems are more common than you'd think - especially in enterprise environments or when working with different **Git** versions across machines. Let's address the most frequent ones.

### The "unknown style 'zdiff3'" error

The most common issue developers face is **Git** throwing an error when trying to set `zdiff3`:

```bash
error: unknown style 'zdiff3' given for 'merge.conflictstyle'
```

This happens because `zdiff3` was introduced in **Git** version 2.35.0 *(released in January 2022)*. If you're running an older version, **Git** simply doesn't know what `zdiff3` is.

First, check your **Git** version:

```bash
git --version
```

If it's older than 2.35.0, you have few options:

- **Upgrade Git** *(recommended)*: On macOS, **Git** usually comes with Xcode Command Line Tools. You can update it by updating Xcode tools with `xcode-select --install`. However, Apple's bundled **Git** often lags behind the latest version. For the newest **Git** version, you might need to install it separately via Homebrew: `brew install git` *(this will install alongside the system version)*. On Ubuntu/Debian systems, you might need to add the official **Git** PPA first to get the latest version.
- **Fall back to diff3**: While not as aggressive in conflict resolution, regular `diff3` still provides the three-way comparison with the common ancestor - which is already miles better than the default `merge` style:

```bash
git config --global merge.conflictstyle diff3
```

### Configuration not taking effect

Sometimes you set the configuration but conflicts still appear in `merge` style. This usually happens due to repository-specific settings overriding global ones. **Git** follows a hierarchy: global → local.

Check what's actually set:

```bash
# Check local repository config
git config merge.conflictstyle

# Check global config
git config --global merge.conflictstyle

# See all merge-related configs
git config --list | grep merge
```

If there's a local override, remove it:

```bash
git config --unset merge.conflictstyle
```

> [!WARNING]
> Some IDEs and **Git** GUIs might override these settings or use their own conflict resolution interfaces, ignoring your CLI configuration entirely

### Conclusion

The `zdiff3` conflict marker is a powerful tool for resolving merge conflicts in **Git**.

- By providing a three-way comparison *(outgoing, common ancestor, incoming)*, it offers developers additional context, helping them understand the evolution of changes and make informed decisions.
- By being more aggressive in its approach to resolving conflicts, it can save developers time and effort by automatically resolving as many conflicts as possible. The more time you spend on the repetative manual work the more error-prone it gets. `zdiff3` is a marvellous way to avoid it and minimize the hassle and frustration.

As collaboration and branch management are integral parts of modern software development, mastering tools like `zdiff3` is essential for maintaining a smooth workflow.

## Want to talk about the article?

[X / @igorklepacki](https://x.com/igorklepacki) · [neg4n@icloud.com](mailto:neg4n@icloud.com)
