diff --git a/cypress/integration/rendering/gitGraph.spec.js b/cypress/integration/rendering/gitGraph.spec.js index 4e8f7fdcac..68b63de469 100644 --- a/cypress/integration/rendering/gitGraph.spec.js +++ b/cypress/integration/rendering/gitGraph.spec.js @@ -1458,5 +1458,79 @@ gitGraph TB: { gitGraph: { parallelCommits: true } } ); }); + it('73: should render a simple gitgraph with three branches and tagged merge commit using switch instead of checkout', () => { + imgSnapshotTest( + `gitGraph + commit id: "1" + commit id: "2" + branch nice_feature + switch nice_feature + commit id: "3" + switch main + commit id: "4" + switch nice_feature + branch very_nice_feature + switch very_nice_feature + commit id: "5" + switch main + commit id: "6" + switch nice_feature + commit id: "7" + switch main + merge nice_feature id: "12345" tag: "my merge commit" + switch very_nice_feature + commit id: "8" + switch main + commit id: "9" + `, + {} + ); + }); + it('74: should render commits for more than 8 branches using switch instead of checkout', () => { + imgSnapshotTest( + ` + gitGraph + switch main + %% Make sure to manually set the ID of all commits, for consistent visual tests + commit id: "1-abcdefg" + switch main + branch branch1 + commit id: "2-abcdefg" + switch main + merge branch1 + branch branch2 + commit id: "3-abcdefg" + switch main + merge branch2 + branch branch3 + commit id: "4-abcdefg" + switch main + merge branch3 + branch branch4 + commit id: "5-abcdefg" + switch main + merge branch4 + branch branch5 + commit id: "6-abcdefg" + switch main + merge branch5 + branch branch6 + commit id: "7-abcdefg" + switch main + merge branch6 + branch branch7 + commit id: "8-abcdefg" + switch main + merge branch7 + branch branch8 + commit id: "9-abcdefg" + switch main + merge branch8 + branch branch9 + commit id: "10-abcdefg" + `, + {} + ); + }); }); }); diff --git a/docs/syntax/gitgraph.md b/docs/syntax/gitgraph.md index b649f4840f..9403f2a334 100644 --- a/docs/syntax/gitgraph.md +++ b/docs/syntax/gitgraph.md @@ -56,6 +56,8 @@ In Mermaid, we support the basic git operations like: With the help of these key git commands, you will be able to draw a gitgraph in Mermaid very easily and quickly. Entity names are often capitalized, although there is no accepted standard on this, and it is not required in Mermaid. +**NOTE**: `checkout` and `switch` can be used interchangeably. + ## Syntax Mermaid syntax for a gitgraph is very straight-forward and simple. It follows a declarative-approach, where each commit is drawn on the timeline in the diagram, in order of its occurrences/presence in code. Basically, it follows the insertion order for each command. diff --git a/packages/mermaid/src/diagrams/git/gitGraphParser.spec.js b/packages/mermaid/src/diagrams/git/gitGraphParser.spec.js index 52cb62fa2d..f6d4e121ae 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphParser.spec.js +++ b/packages/mermaid/src/diagrams/git/gitGraphParser.spec.js @@ -88,6 +88,16 @@ describe('when parsing a gitGraph', function () { expect(parser.yy.getCurrentBranch()).toBe('new'); }); + it('should switch a branch', function () { + const str = 'gitGraph:\n' + 'branch new\n' + 'switch new\n'; + + parser.parse(str); + const commits = parser.yy.getCommits(); + + expect(Object.keys(commits).length).toBe(0); + expect(parser.yy.getCurrentBranch()).toBe('new'); + }); + it('should add commits to checked out branch', function () { const str = 'gitGraph:\n' + 'branch new\n' + 'checkout new\n' + 'commit\n' + 'commit\n'; diff --git a/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js b/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js index 09a9cdb259..ac85712b2b 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js +++ b/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js @@ -520,6 +520,78 @@ describe('when parsing a gitGraph', function () { ]); }); + it('should handle new branch switch', function () { + const str = `gitGraph: + commit + branch testBranch + switch testBranch + `; + + parser.parse(str); + const commits = parser.yy.getCommits(); + expect(Object.keys(commits).length).toBe(1); + expect(parser.yy.getCurrentBranch()).toBe('testBranch'); + expect(parser.yy.getDirection()).toBe('LR'); + expect(Object.keys(parser.yy.getBranches()).length).toBe(2); + }); + + it('should handle new branch switch & commit', function () { + const str = `gitGraph: + commit + branch testBranch + switch testBranch + commit + `; + + parser.parse(str); + const commits = parser.yy.getCommits(); + expect(Object.keys(commits).length).toBe(2); + expect(parser.yy.getCurrentBranch()).toBe('testBranch'); + expect(parser.yy.getDirection()).toBe('LR'); + expect(Object.keys(parser.yy.getBranches()).length).toBe(2); + const commit1 = Object.keys(commits)[0]; + const commit2 = Object.keys(commits)[1]; + expect(commits[commit1].branch).toBe('main'); + expect(commits[commit1].parents).toStrictEqual([]); + expect(commits[commit2].branch).toBe('testBranch'); + expect(commits[commit2].parents).toStrictEqual([commit1]); + }); + + it('should handle new branch switch & commit and merge', function () { + const str = `gitGraph: + commit + branch testBranch + switch testBranch + commit + commit + switch main + merge testBranch + `; + + parser.parse(str); + const commits = parser.yy.getCommits(); + expect(Object.keys(commits).length).toBe(4); + expect(parser.yy.getCurrentBranch()).toBe('main'); + expect(parser.yy.getDirection()).toBe('LR'); + expect(Object.keys(parser.yy.getBranches()).length).toBe(2); + const commit1 = Object.keys(commits)[0]; + const commit2 = Object.keys(commits)[1]; + const commit3 = Object.keys(commits)[2]; + const commit4 = Object.keys(commits)[3]; + expect(commits[commit1].branch).toBe('main'); + expect(commits[commit1].parents).toStrictEqual([]); + expect(commits[commit2].branch).toBe('testBranch'); + expect(commits[commit2].parents).toStrictEqual([commits[commit1].id]); + expect(commits[commit3].branch).toBe('testBranch'); + expect(commits[commit3].parents).toStrictEqual([commits[commit2].id]); + expect(commits[commit4].branch).toBe('main'); + expect(commits[commit4].parents).toStrictEqual([commits[commit1].id, commits[commit3].id]); + expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([ + { name: 'main' }, + { name: 'testBranch' }, + ]); + }); + it('should handle merge tags', function () { const str = `gitGraph: commit diff --git a/packages/mermaid/src/diagrams/git/parser/gitGraph.jison b/packages/mermaid/src/diagrams/git/parser/gitGraph.jison index 07d1a3e410..b4670ca0b7 100644 --- a/packages/mermaid/src/diagrams/git/parser/gitGraph.jison +++ b/packages/mermaid/src/diagrams/git/parser/gitGraph.jison @@ -41,7 +41,7 @@ merge(?=\s|$) return 'MERGE'; cherry\-pick(?=\s|$) return 'CHERRY_PICK'; "parent:" return 'PARENT_COMMIT' // "reset" return 'RESET'; -checkout(?=\s|$) return 'CHECKOUT'; +\b(checkout|switch)(?=\s|$) return 'CHECKOUT'; "LR" return 'DIR'; "TB" return 'DIR'; "BT" return 'DIR'; diff --git a/packages/mermaid/src/docs/syntax/gitgraph.md b/packages/mermaid/src/docs/syntax/gitgraph.md index ce9aa507e8..d0791718b8 100644 --- a/packages/mermaid/src/docs/syntax/gitgraph.md +++ b/packages/mermaid/src/docs/syntax/gitgraph.md @@ -33,6 +33,8 @@ In Mermaid, we support the basic git operations like: With the help of these key git commands, you will be able to draw a gitgraph in Mermaid very easily and quickly. Entity names are often capitalized, although there is no accepted standard on this, and it is not required in Mermaid. +**NOTE**: `checkout` and `switch` can be used interchangeably. + ## Syntax Mermaid syntax for a gitgraph is very straight-forward and simple. It follows a declarative-approach, where each commit is drawn on the timeline in the diagram, in order of its occurrences/presence in code. Basically, it follows the insertion order for each command.