Comparing Branches

Introduction

In Contentstack, the Branch Compare feature allows users to analyze the differences between two branches: the Base branch (typically 'main') and the Compare branch (where desired changes are made). This comparison serves to understand changes before merging them into the base branch.

Methods of Comparison

When comparing branches, users can view differences in:
- Content types and global fields
- Specific content types
- Specific global fields

Comparison Status:

Three outcomes are possible:
1. Base only: base only notifies that a particular content type or global field is present only in the base branch and is not present in the compare branch.
2. Compare only: compare only notifies that a particular content type or global field is present only in the compare branch and is not present in the base branch.
3. Modified: The item exists in both branches but has been altered.

Use Cases:

1. Modifying a Content Type:
- Scenario: Altering fields without impacting the source branch.
- Approach: Create a child branch inheriting from the main branch, make changes, and then compare.
- Status: Differences are marked as "modified."

We are going to modify the fields present in the Author content type.
Let's first see the structure of the Author content type in the source branch i.e., in the main branch.

BranchesFoundations-L6-img-1.png

We will change field names First Name to Author First Name and Last Name to Author Last Name in the compare branch i.e., dev branch.


Also, we are going to change the field from SEO Global field

Let's first see the structure of the SEO Global field  in the source branch i.e., in the main branch

BranchesFoundations-L6-img-2.png

We changed the Meta Title filed to the SEO Meta Title in the dev branch.

BranchesFoundations-L6-img-3.png

2. Adding a New Feature:
- Scenario: Introducing a new content type.
- Approach: Create a new branch, make changes, and then compare with the main branch.
- Status: Differences are marked as "compare only" if the new content type is only in the compare branch.

We are going to add a new content type named "Branch Demo" in the dev branch

BranchesFoundations-L6-img-4.png


BranchesFoundations-L6-img-5.png

Now let's do the comparison by using Content Management API as well as CLI

First will see all compare operations with API
1)  Compare branch

curl --location 'https://api.contentstack.io/v3/stacks/branches_compare?compare_branch=dev'

\ --header 'api_key: *****************'

\ --header 'authorization: ******************'

\ --header 'Content-Type: application/json'

\ --data ''


Result

{

    "branches": {

        "base_branch": "main",

        "compare_branch": "dev"

    },

    "diff": [

        {

            "title": "SEO",

            "uid": "seo",

            "type": "global_field",

            "status": "modified"

        },

        {

            "title": "Branch Demo",

            "uid": "branch_demo",

            "type": "content_type",

            "status": "compare_only"

        },

        {

            "title": "Author",

            "uid": "author",

            "type": "content_type",

            "status": "modified"

        }

    ]

}

BranchesFoundations-L6-img-6.png

2) Compare Content Type between Branches

curl --location 'https://api.contentstack.io/v3/stacks/branches_compare/content_types?compare_branch=dev' \
--header 'api_key: ******************' \
--header 'authorization: ******************' \
--header 'Content-Type: application/json' \
--data ''

Result

{

    "branches": {

        "base_branch": "main",

        "compare_branch": "dev"

    },

    "diff": [

        {

            "title": "Branch Demo",

            "uid": "branch_demo",

            "type": "content_type",

            "status": "compare_only"

        },

        {

            "title": "Author",

            "uid": "author",

            "type": "content_type",

            "status": "modified"

        }

    ]

}

BranchesFoundations-L6-img-7.png

3) Compare Global Fields between Branches

curl --location 'https://api.contentstack.io/v3/stacks/branches_compare/global_fields?compare_branch=dev' \
--header 'api_key: *****************' \
--header 'authorization: ********************' \
--header 'Content-Type: application/json' \
--data ''

Result

{

    "branches": {

        "base_branch": "main",

        "compare_branch": "dev"

    },

    "diff": [

        {

            "title": "SEO",

            "uid": "seo",

            "type": "global_field",

            "status": "modified"

        }

    ]

}

BranchesFoundations-L6-img-8.png

4) Compare Specific Content Types between Branches

curl --location 'https://api.contentstack.io/v3/stacks/branches_compare/content_types/author?compare_branch=dev' \
--header 'api_key: ******************' \
--header 'authorization: *******************' \
--header 'Content-Type: application/json' \
--data ''

Result

{

    "branches": {

        "base_branch": "main",

        "compare_branch": "dev"

    },

    "diff": {

        "uid": "author",

        "type": "content_type",

        "status": "modified",

        "base_branch": {

            "differences": [

                {

                    "display_name": "First Name",

                    "uid": "title",

                    "data_type": "text",

                    "mandatory": true,

                    "unique": true,

                    "field_metadata": {

                        "_default": true,

                        "version": 3

                    },

                    "multiple": false,

                    "non_localizable": false,

                    "indexed": false,

                    "inbuilt_model": false,

                    "path": "schema[0]"

                },

                {

                    "data_type": "text",

                    "display_name": "Last Name",

                    "uid": "last_name",

                    "field_metadata": {

                        "description": "",

                        "default_value": "",

                        "version": 3

                    },

                    "format": "",

                    "error_messages": {

                        "format": ""

                    },

                    "mandatory": false,

                    "multiple": false,

                    "non_localizable": false,

                    "unique": false,

                    "indexed": false,

                    "inbuilt_model": false,

                    "path": "schema[1]"

                }

            ],

            "schema": null

        },

        "compare_branch": {

            "differences": [

                {

                    "display_name": "Author First Name",

                    "uid": "title",

                    "data_type": "text",

                    "mandatory": true,

                    "unique": true,

                    "field_metadata": {

                        "_default": true,

                        "version": 3

                    },

                    "multiple": false,

                    "non_localizable": false,

                    "indexed": false,

                    "inbuilt_model": false,

                    "path": "schema[0]"

                },

                {

                    "data_type": "text",

                    "display_name": "Author Last Name",

                    "uid": "last_name_dev",

                    "field_metadata": {

                        "description": "",

                        "default_value": "",

                        "version": 3

                    },

                    "format": "",

                    "error_messages": {

                        "format": ""

                    },

                    "mandatory": false,

                    "multiple": false,

                    "non_localizable": false,

                    "unique": false,

                    "indexed": false,

                    "inbuilt_model": false,

                    "path": "schema[1]"

                }

            ],

            "schema": null

        }

    }

}

BranchesFoundations-L6-img-9.png

5) Compare Specific Global Fields between Branches

curl --location 'https://api.contentstack.io/v3/stacks/branches_compare/global_fields/seo?compare_branch=dev' \
--header 'api_key: *****************' \
--header 'authorization: *********************' \
--header 'Content-Type: application/json' \
--data ''

Result

{

    "branches": {

        "base_branch": "main",

        "compare_branch": "dev"

    },

    "diff": {

        "uid": "seo",

        "type": "global_field",

        "status": "modified",

        "base_branch": {

            "differences": [

                {

                    "data_type": "text",

                    "display_name": "Meta Title",

                    "uid": "meta_title",

                    "field_metadata": {

                        "description": "",

                        "default_value": "",

                        "version": 3

                    },

                    "format": "",

                    "error_messages": {

                        "format": ""

                    },

                    "multiple": false,

                    "mandatory": false,

                    "unique": false,

                    "non_localizable": false,

                    "indexed": false,

                    "inbuilt_model": false,

                    "path": "schema[0]"

                }

            ],

            "schema": null

        },

        "compare_branch": {

            "differences": [

                {

                    "data_type": "text",

                    "display_name": "SEO Meta Title",

                    "uid": "meta_title",

                    "field_metadata": {

                        "description": "",

                        "default_value": "",

                        "version": 3

                    },

                    "format": "",

                    "error_messages": {

                        "format": ""

                    },

                    "multiple": false,

                    "mandatory": false,

                    "unique": false,

                    "non_localizable": false,

                    "indexed": false,

                    "inbuilt_model": false,

                    "path": "schema[0]"

                }

            ],

            "schema": null

        }

    }

}

BranchesFoundations-L6-img-10.png

Now let's see all compare operations using the Command Line Interface (CLI)

The comparison results are distinguished based on the following:

  1. A “+” symbol with green highlighted text: Indicates that this is present only in the compare branch.

  2. A “±” symbol with blue highlighted text Indicates that this is present in both branches but has different values.

  3. A “-” symbol with red highlighted text: Indicates that this is not present in the compare branch.


csdx cm:branches:diff --help
Differences between two branches

USAGE
  $ csdx cm:branches:diff [--base-branch ] [--compare-branch ] [-k ][--module ]

FLAGS
  -k, --stack-api-key=  Provide Stack API key to show difference between branches
  --base-branch=        Base branch
  --compare-branch=     Compare branch
  --format=            [default: compact-text] [Optional] Type of flags to show branches differences

  --module=            Module

DESCRIPTION
  Differences between two branches

EXAMPLES
  $ csdx cm:branches:diff

  $ csdx cm:branches:diff --stack-api-key "bltxxxxxxxx"

  $ csdx cm:branches:diff --compare-branch "dev"

  $ csdx cm:branches:diff --compare-branch "dev" --stack-api-key "bltxxxxxxxx"

  $ csdx cm:branches:diff --compare-branch "dev" --module "content-types"

  $ csdx cm:branches:diff --module "content-types" --format "detailed-text"

  $ csdx cm:branches:diff --compare-branch "dev" --format "detailed-text"

  $ csdx cm:branches:diff --stack-api-key "bltxxxxxxxx" --base-branch "main"

  $ csdx cm:branches:diff --stack-api-key "bltxxxxxxxx" --base-branch "main" --compare-branch "dev"

  $ csdx cm:branches:diff --stack-api-key "bltxxxxxxxx" --base-branch "main" --module "content-types"

  $ csdx cm:branches:diff --stack-api-key "bltxxxxxxxx" --base-branch "main" --compare-branch "dev" --module "content-types"

  $ csdx cm:branches:diff --stack-api-key "bltxxxxxxxx" --base-branch "main" --compare-branch "dev" --module "content-types" --format "detailed-text"

1) Get all module's difference

BranchesFoundations-L6-img-11.png

2) Get all content types difference

BranchesFoundations-L6-img-12.png

3) Get all global fields' difference

BranchesFoundations-L6-img-13.png

Conclusion:

Comparing branches in Contentstack facilitates safe development and integration of changes, allowing users to manage modifications effectively before merging them into the main branch.


Further Reference