# Compare and merge - branch reconciliation mechanics

### About this export

| Field | Value |
| --- | --- |
| **content_type** | lesson |
| **platform** | contentstack-academy |
| **source_url** | https://www.contentstack.com/academy/courses/workflow-branches-and-collaboration/compare-and-merge-branch-reconciliation-mechanics |
| **course_slug** | workflow-branches-and-collaboration |
| **lesson_slug** | compare-and-merge-branch-reconciliation-mechanics |
| **markdown_file_url** | /academy/md/courses/workflow-branches-and-collaboration/compare-and-merge-branch-reconciliation-mechanics.md |
| **generated_at** | 2026-08-03T11:49:54.442Z |

> Part of **[Workflow, Branches, and Collaboration](https://www.contentstack.com/academy/courses/workflow-branches-and-collaboration)** on Contentstack Academy. **Academy MD v3** — structured for retrieval; no quiz or assessment keys.

<!-- ai_metadata: {"lesson_id":"07","type":"text","duration_minutes":1,"topics":["Compare","and","merge","branch","reconciliation","mechanics"]} -->

#### Lesson text

# Compare and merge: branch reconciliation mechanics

> **TL;DR:**
> 
> *   Always use the compare view before merging — it shows field-level additions, removals, and modifications across content types.
> *   Field removal in a merge means permanent data loss on existing entries; verify before proceeding.
> *   Merges cannot be automatically reversed; create a backup branch from the target before merging.

Creating a branch is straightforward. Merging it back is where the real work happens. A branch that has been evolving independently for days or weeks contains content type changes that must be reconciled with whatever has happened on the target branch in the same period. Contentstack provides a compare-and-merge workflow that lets you inspect differences between branches at the field level, understand what will change, and execute the merge with confidence. Skipping the comparison step or rushing the merge is how teams break production content models.

> **Common pitfall:**
> 
> When a merge removes a field from a content type, all data in that field on existing entries is permanently deleted. There is no undo. Always verify that removed-field data has been migrated or is genuinely no longer needed before merging.

## The compare feature

Before merging anything, you need to see exactly what has changed. The compare feature shows the differences between two branches - typically your working branch and main - at the content type and field level.

You access the compare view from **Settings > Branches** in the Contentstack UI. Select your branch and click “Compare” to see a side-by-side diff against the target branch (usually main).

The compare view organizes differences into three categories:

**Added content types:** content types that exist on your branch but not on the target. These were created on the branch after it was forked. Merging will add these content types to the target branch.

**Modified content types:** content types that exist on both branches but have different schemas. The compare view shows field-level differences: which fields were added, removed, or changed on each branch.

**Deleted content types:** content types that exist on the target branch but were removed from your branch. Merging will remove these content types from the target. This is a destructive operation and requires careful consideration - deleting a content type on the target branch also removes all entries of that type.

## Field-level diff

The compare view does not just tell you that a content type was modified. It shows exactly what changed at the field level:

Diff type

What it means

Field added

A new field exists on the branch that does not exist on target

Field removed

A field was deleted on the branch that still exists on target

Field modified

A field exists on both branches but has different properties

For modified fields, the diff shows what changed: the field type, the display name, validation rules, default values, field-level help text, or whether the field is required. This granularity is essential for understanding the impact of a merge.

Consider a “Product” content type where the branch made these changes:

Product content type diff:
+ specifications (modular\_blocks)     -  new field added on branch
+ long\_description (rich\_text)        -  new field added on branch
~ description → short\_description     -  field renamed on branch
- legacy\_sku (text)                   -  field removed on branch

This diff tells you exactly what will happen to the Product content type on main if you merge: two new fields appear, one field gets renamed, and one field is removed. The removed field means any data in legacy\_sku on main branch entries will be lost after merge. The renamed field means frontend code referencing description must be updated to reference short\_description.

## The merge operation

Once you have reviewed the diff and are confident in the changes, you execute the merge. The merge applies all changes from the source branch to the target branch.

Through the UI: from the compare view, click “Merge.” Contentstack shows a summary of all changes that will be applied and asks for confirmation.

Through the API: use the branch merge endpoint.

// Merging a branch into main via the Management API
const response = await fetch(
  "https://api.contentstack.io/v3/stacks/branches\_merge",
  {
    method: "POST",
    headers: {
      api\_key: process.env.NEXT\_PUBLIC\_CONTENTSTACK\_API\_KEY!,
      authorization: process.env.NEXT\_PUBLIC\_CONTENTSTACK\_MANAGEMENT\_TOKEN!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      base\_branch: "main",
      compare\_branch: "feature-product-redesign",
      merge\_strategy: "merge\_prefer\_base",
      merge\_comment: "Merging product redesign: new specifications block, description rename, legacy\_sku removal",
    }),
  }
);

const result = await response.json();
console.log(\`Merge status: ${result.merge\_details.status}\`);

The merge operation is not instantaneous. Contentstack processes the changes asynchronously, applying field additions, removals, and modifications to the target branch's content types. For large merges affecting many content types, this may take several minutes.

## What happens during a merge

Understanding the mechanics of a merge helps you predict its impact and plan accordingly.

**New content types** are created on the target branch with the same schema they have on the source branch. If your branch added a “Gallery” content type with 8 fields, the target branch gets a “Gallery” content type with those same 8 fields. No entries are created - only the content type definition is merged.

**Modified content types** have their schemas updated to reflect the branch's changes. Added fields appear on the target. Removed fields disappear from the target. Modified fields take on the branch's configuration. Existing entries on the target branch are affected:

*   New fields appear with empty/null values on existing entries.
*   Removed fields and their data are gone. Entries that had data in those fields lose it.
*   Modified fields retain their data but the field properties (validation, help text, etc.) change.

**Deleted content types** are removed from the target branch, along with all their entries. This is the most destructive merge outcome and should be reviewed carefully.

## Conflict resolution

Conflicts arise when both branches modify the same content type. If your branch renamed a field from description to short\_description and main independently added a validation rule to the description field, a conflict appears: the field the main branch modified no longer exists in the same form on your branch.

Contentstack resolves conflicts using a selected merge strategy, not a universal “source wins” rule. Common strategies include:

*   merge\_prefer\_base (default): prefer target/base branch values on conflicts.
*   merge\_prefer\_compare: prefer source/compare branch values on conflicts.
*   overwrite\_with\_compare: force compare branch values over base.
*   merge\_new\_only: merge only additions and leave existing conflicting definitions unchanged.

This means you must choose a strategy intentionally and review the compare diff before merging.

For complex conflicts, the recommended approach is:

1.  Compare your branch to the target and identify all conflicts.
2.  Decide how each conflict should be resolved.
3.  If the chosen strategy will not produce the correct result, update your branch (or change the strategy) before merging.
4.  Re-compare to confirm the merge will produce the desired result.
5.  Execute the merge.

## Pre-merge checklist

Before executing any merge, work through this checklist:

**Review all content type changes.** Use the compare view to inspect every added, modified, and deleted content type. Understand the impact of each change on existing entries and frontend code.

**Check for field removals.** Any field removed by the merge means data loss for entries on the target branch that used that field. Verify that the data is no longer needed, or that it has been migrated to a different field.

**Verify that target branch content types will not break existing entries.** If you are adding a required field, existing entries on the target branch will be invalid until they are updated. Consider making new fields optional during the merge, then making them required after existing entries are populated.

**Coordinate with the frontend team.** If the merge changes the delivery API response shape (new fields, removed fields, renamed fields), the frontend code must be updated. Plan the merge and the frontend deployment together.

**Communicate with the content team.** Editors working on main should know that content type changes are coming. If the merge modifies content types they actively use, they may encounter new fields, changed field labels, or modified validation rules.

**Choose your timing.** Merge during low-traffic periods when fewer editors are actively working. A merge that changes the schema of a content type currently being edited can create confusion.

// Pre-merge: list all content types on both branches to audit differences
async function auditBranchDifferences(sourceBranch: string, targetBranch: string) {
  const fetchContentTypes = async (branch: string) => {
    const response = await fetch(
      "https://api.contentstack.io/v3/content\_types",
      {
        headers: {
          api\_key: process.env.NEXT\_PUBLIC\_CONTENTSTACK\_API\_KEY!,
          authorization: process.env.NEXT\_PUBLIC\_CONTENTSTACK\_MANAGEMENT\_TOKEN!,
          branch,
        },
      }
    );
    const data = await response.json();
    return data.content\_types;
  };

  const sourceTypes = await fetchContentTypes(sourceBranch);
  const targetTypes = await fetchContentTypes(targetBranch);

  const sourceUids = new Set(sourceTypes.map((ct: any) => ct.uid));
  const targetUids = new Set(targetTypes.map((ct: any) => ct.uid));

  const added = sourceTypes.filter((ct: any) => !targetUids.has(ct.uid));
  const removed = targetTypes.filter((ct: any) => !sourceUids.has(ct.uid));

  console.log(\`Content types added on ${sourceBranch}: ${added.map((ct: any) => ct.uid).join(", ")}\`);
  console.log(\`Content types removed on ${sourceBranch}: ${removed.map((ct: any) => ct.uid).join(", ")}\`);
}

auditBranchDifferences("feature-product-redesign", "main");

## Post-merge actions

The merge is not the end of the process. Several follow-up actions are required to ensure the merged content model works correctly.

**Verify the merged content types.** Open each modified content type on the target branch and confirm the schema matches your expectations. Check field order, field types, validation rules, and display names.

**Test the delivery API.** Query the delivery API for affected content types and verify the response shape. New fields should appear (with null or empty values on existing entries). Removed fields should be absent. Renamed fields should use the new name.

// Post-merge: verify the delivery API returns the expected schema
const stack = contentstack.stack({
  apiKey: process.env.NEXT\_PUBLIC\_CONTENTSTACK\_API\_KEY!,
  deliveryToken: process.env.NEXT\_PUBLIC\_CONTENTSTACK\_DELIVERY\_TOKEN!,
  environment: "development",
  // No branch parameter  -  querying main after merge
});

const result = await stack
  .contentType("product")
  .entry()
  .query()
  .find();

const sampleProduct = result.entries\[0\];
console.log("Has specifications:", "specifications" in sampleProduct);
console.log("Has short\_description:", "short\_description" in sampleProduct);
console.log("Has legacy\_sku:", "legacy\_sku" in sampleProduct);
// Expected: true, true, false

**Update frontend code.** Deploy frontend changes that align with the new content model. If you renamed description to short\_description, your frontend components need to use the new field name. Ideally, the frontend code is already prepared (tested against the branch API) and just needs to be deployed.

**Re-publish affected entries.** If content type structure changed in ways that affect delivery, existing entries may need to be re-published. An entry published before the merge was published with the old schema. Re-publishing it ensures the delivery API serves it with the new schema.

**Populate new required fields.** If the merge added required fields, existing entries on the target branch are now technically invalid. Editors need to update those entries with values for the new required fields before they can be saved or re-published.

## Entry handling during merge

Entries on the source branch and entries on the target branch are largely independent. The merge operation focuses on content type schemas, not entries. However, the schema changes affect entries indirectly:

*   Entries on the target branch that belong to modified content types will reflect the new schema after merge. New fields appear empty. Removed fields and their data are gone.
*   Entries that were created on the source branch are not automatically copied to the target branch during a merge. Only the content type definitions are merged.
*   If you need entries from the source branch on the target branch, you must handle that separately - either through export/import, the Management API, or manual re-creation.

This is an important distinction. A merge moves schema changes, not content. If your branch had test entries that you want to keep, plan for their migration separately.

## Limitations: merges cannot be automatically reversed

There is no “undo merge” button in Contentstack. Once a merge is executed, the target branch's content types are permanently modified. If the merge introduced a problem, you have a few remediation options:

*   Manual revert: modify the target branch's content types to restore the pre-merge state. This is tedious but possible for small changes.
*   Restore from a backup branch: if you created a backup branch from the target before merging (a recommended practice), you can compare the backup to the current state and selectively revert changes.
*   Re-create and re-merge: if the merge was fundamentally wrong, you may need to create a new branch from the backup, apply only the correct changes, and merge again.

The irreversibility of merges is why the pre-merge checklist and the compare review matter. Review every change before merging.

## Example: merging a redesign branch with a conflict

Veda has been working on a feature/homepage-redesign branch for two weeks. On this branch, they:

1.  Added a “modular\_blocks” field called components to the “Page” content type, replacing the old hero\_image and hero\_title fields.
2.  Created a new “Product Line” content type with 10 fields.
3.  Removed the deprecated “Legacy Banner” content type.

During the same two weeks, a developer on main independently added a promotional\_image field to the “Page” content type to support a short-term promotion.

When the team runs the compare view, they see:

Page content type:

*   Branch added: components (modular\_blocks)
*   Branch removed: hero\_image (file), hero\_title (text)
*   Main added: promotional\_image (file) - this is a conflict area

Product Line content type:

*   Entirely new on the branch. Will be added to main.

Legacy Banner content type:

*   Deleted on the branch. Will be removed from main (and all its entries).

The conflict on the Page content type is that the branch does not have the promotional\_image field that main added. If they merge directly, promotional\_image will be removed from main (because it does not exist on the branch).

The resolution process:

1.  The team adds the promotional\_image field to the Page content type on the branch, preserving the main branch's addition.
2.  They re-run the compare and confirm that promotional\_image now appears on both branches (no conflict).
3.  They verify that the “Legacy Banner” content type's entries are no longer needed.
4.  They execute the merge.
5.  Post-merge, they verify that Page has components, promotional\_image, and no longer has hero\_image or hero\_title.
6.  They deploy the updated frontend that renders the new modular hero sections.
7.  They schedule the eventual removal of promotional\_image once the promotion ends.

## Common mistakes

### Mistake 1: Merging without reviewing the compare diff

Every merge has the potential to remove fields, delete content types, and change data structures. Merging without reviewing the diff is equivalent to deploying code without reading the pull request. Always use the compare view before merging, even for branches where you think you know what changed.

### Mistake 2: Forgetting that field removal means data loss

When a merge removes a field from a content type, all data in that field on existing entries is permanently deleted. This is not a reversible operation. Before merging a branch that removes fields, verify that the data in those fields is either migrated to a new location or genuinely no longer needed.

### Mistake 3: Not coordinating the merge with frontend deployment

A merge that changes the delivery API response shape (new fields, removed fields, renamed fields) without a corresponding frontend update results in a broken site. Plan merges and frontend deployments as a coordinated operation. The ideal sequence is: deploy frontend code that handles both old and new schemas, execute the merge, then deploy frontend code that only handles the new schema.

#### Key takeaways

- Connect **Compare and merge - branch reconciliation mechanics** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

## Supplement for indexing

### Content summary

Compare and merge - branch reconciliation mechanics. Compare and merge: branch reconciliation mechanics TL;DR: Always use the compare view before merging — it shows field-level additions, removals, and modifications across content types. Field removal in a merge means permanent data loss on existing entries; verify before proceeding. Merges cannot be automatically reversed; create a backup branch from the target before merging. Creating a branch is straightforward. Merging it back is where the real work happens. A branch that has been evolving independently for days or weeks contains content type changes that must be reconciled with whatever has happened on the target branch in the same period. Contentstack provides a compare-and-merge workflo

### Retrieval tags

- Compare
- and
- merge
- branch
- reconciliation
- mechanics
- workflow-branches-and-collaboration
- lesson 07
- Compare and merge - branch reconciliation mechanics
- workflow-branches-and-collaboration lesson

### Indexing notes

Index this lesson as a primary chunk tagged with lesson_id "07" and topics: [Compare, and, merge, branch, reconciliation, mechanics].
Parent course slug: workflow-branches-and-collaboration. Use asset_references URLs as thumbnail hints in search results when present.
Never surface LMS quiz content or assessment answers from this file.

### Asset references

_No image or video thumbnail URLs were extracted._

### External links

| Label | URL |
| --- | --- |
| Contentstack Academy home | `https://www.contentstack.com/academy/` |
| Training instance setup | `https://www.contentstack.com/academy/training-instance` |
| Academy playground (GitHub) | `https://github.com/contentstack/contentstack-academy-playground` |
| Contentstack documentation | `https://www.contentstack.com/docs/` |
