Merge pull request #3379 from mermaid-js/3238_Gitgraph_merge_commits
3238 gitgraph merge commits
This commit is contained in:
commit
065a3176b8
|
@ -253,4 +253,32 @@ describe('Git Graph diagram', () => {
|
|||
{}
|
||||
);
|
||||
});
|
||||
it('13: should render a simple gitgraph with three branches,custom merge commit id,tag,type', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
checkout nice_feature
|
||||
commit id: "3"
|
||||
checkout main
|
||||
commit id: "4"
|
||||
checkout nice_feature
|
||||
branch very_nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "5"
|
||||
checkout main
|
||||
commit id: "6"
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature id: "customID" tag: "customTag" type: REVERSE
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
commit id: "9"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -182,7 +182,40 @@ After this we made use of the `checkout` keyword to set the current branch as `m
|
|||
After this we merge the `develop` branch onto the current branch `main`, resulting in a merge commit.
|
||||
Since the current branch at this point is still `main`, the last two commits are registered against that.
|
||||
|
||||
Additionally, you may add a tag to the merge commit, or override the default id: `merge branch id:"1234" tag:"v1.0.0"`
|
||||
You can also decorate your merge with similar attributes as you did for the commit using:
|
||||
- `id`--> To override the default ID with custom ID
|
||||
- `tag`--> To add a custom tag to your merge commit
|
||||
- `type`--> To override the default shape of merge commit. Here you can use other commit type mentioned earlier.
|
||||
|
||||
And you can choose to use none, some or all of these attributes together.
|
||||
For example: `merge develop id: "my_custom_id" tag: "my_custom_tag" type: REVERSE`
|
||||
|
||||
Let us see how this works with the help of the following diagram:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
checkout nice_feature
|
||||
commit id: "3"
|
||||
checkout main
|
||||
commit id: "4"
|
||||
checkout nice_feature
|
||||
branch very_nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "5"
|
||||
checkout main
|
||||
commit id: "6"
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature id: "customID" tag: "customTag" type: REVERSE
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
commit id: "9"
|
||||
```
|
||||
|
||||
### Cherry Pick commit from another branch
|
||||
Similar to how 'git' allows you to cherry-pick a commit from **another branch** onto the **current** branch, Mermaid also supports this functionality. You can also cherry-pick a commit from another branch using the `cherry-pick` keyword.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mermaid",
|
||||
"version": "9.1.5",
|
||||
"version": "9.1.6",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"main": "dist/mermaid.min.js",
|
||||
"module": "dist/mermaid.esm.min.mjs",
|
||||
|
|
|
@ -148,16 +148,9 @@ export const branch = function (name, order) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a merge commit.
|
||||
*
|
||||
* @param {string} otherBranch - Target branch to merge to.
|
||||
* @param {string} [tag] - Git tag to use on this merge commit.
|
||||
* @param {string} [id] - Git commit id.
|
||||
*/
|
||||
export const merge = function (otherBranch, tag, id) {
|
||||
export const merge = function (otherBranch, custom_id, override_type, custom_tag) {
|
||||
otherBranch = common.sanitizeText(otherBranch, configApi.getConfig());
|
||||
id = common.sanitizeText(id, configApi.getConfig());
|
||||
custom_id = common.sanitizeText(custom_id, configApi.getConfig());
|
||||
|
||||
const currentCommit = commits[branches[curBranch]];
|
||||
const otherCommit = commits[branches[otherBranch]];
|
||||
|
@ -216,6 +209,23 @@ export const merge = function (otherBranch, tag, id) {
|
|||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['branch abc'],
|
||||
};
|
||||
throw error;
|
||||
} else if (custom_id && typeof commits[custom_id] !== 'undefined') {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "merge". Commit with id:' +
|
||||
custom_id +
|
||||
' already exists, use different custom Id'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch + custom_id + override_type + custom_tag,
|
||||
token: 'merge ' + otherBranch + custom_id + override_type + custom_tag,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: [
|
||||
'merge ' + otherBranch + ' ' + custom_id + '_UNIQUE ' + override_type + ' ' + custom_tag,
|
||||
],
|
||||
};
|
||||
|
||||
throw error;
|
||||
}
|
||||
// if (isReachableFrom(currentCommit, otherCommit)) {
|
||||
|
@ -228,13 +238,15 @@ export const merge = function (otherBranch, tag, id) {
|
|||
// } else {
|
||||
// create merge commit
|
||||
const commit = {
|
||||
id: id || seq + '-' + getId(),
|
||||
id: custom_id ? custom_id : seq + '-' + getId(),
|
||||
message: 'merged branch ' + otherBranch + ' into ' + curBranch,
|
||||
seq: seq++,
|
||||
parents: [head == null ? null : head.id, branches[otherBranch]],
|
||||
branch: curBranch,
|
||||
type: commitType.MERGE,
|
||||
tag: tag ? tag : '',
|
||||
customType: override_type,
|
||||
customId: custom_id ? true : false,
|
||||
tag: custom_tag ? custom_tag : '',
|
||||
};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
|
|
|
@ -496,7 +496,7 @@ describe('when parsing a gitGraph', function () {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should handle merge ids', function () {
|
||||
it('should handle merge with custom ids, tags and typr', function () {
|
||||
const str = `gitGraph:
|
||||
commit
|
||||
branch testBranch
|
||||
|
@ -510,7 +510,7 @@ describe('when parsing a gitGraph', function () {
|
|||
commit
|
||||
checkout main
|
||||
%% Merge ID and Tag (reverse order)
|
||||
merge testBranch2 id: "4-444" tag: "merge-tag2"
|
||||
merge testBranch2 id: "4-444" tag: "merge-tag2" type:HIGHLIGHT
|
||||
branch testBranch3
|
||||
checkout testBranch3
|
||||
commit
|
||||
|
@ -553,6 +553,8 @@ describe('when parsing a gitGraph', function () {
|
|||
expect(testBranch2Merge.parents).toStrictEqual([testBranchMerge.id, testBranch2Commit.id]);
|
||||
expect(testBranch2Merge.tag).toBe('merge-tag2');
|
||||
expect(testBranch2Merge.id).toBe('4-444');
|
||||
expect(testBranch2Merge.customType).toBe(2);
|
||||
expect(testBranch2Merge.customId).toBe(true);
|
||||
|
||||
expect(testBranch3Merge.branch).toBe('main');
|
||||
expect(testBranch3Merge.parents).toStrictEqual([testBranch2Merge.id, testBranch3Commit.id]);
|
||||
|
@ -687,6 +689,27 @@ describe('when parsing a gitGraph', function () {
|
|||
expect(e.message).toBe('Incorrect usage of "merge". Cannot merge a branch to itself');
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw error when using existing id as merge ID', function () {
|
||||
const str = `gitGraph
|
||||
commit id: "1-111"
|
||||
branch testBranch
|
||||
commit id: "2-222"
|
||||
commit id: "3-333"
|
||||
checkout main
|
||||
merge testBranch id: "1-111"
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe(
|
||||
'Incorrect usage of "merge". Commit with id:1-111 already exists, use different custom Id'
|
||||
);
|
||||
}
|
||||
});
|
||||
it('should throw error when trying to merge branches having same heads', function () {
|
||||
const str = `gitGraph
|
||||
commit
|
||||
|
|
|
@ -91,7 +91,9 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
// Don't draw the commits now but calculate the positioning which is used by the branch lines etc.
|
||||
if (modifyGraph) {
|
||||
let typeClass;
|
||||
switch (commit.type) {
|
||||
let commitSymbolType =
|
||||
typeof commit.customType !== 'undefined' ? commit.customType : commit.type;
|
||||
switch (commitSymbolType) {
|
||||
case commitType.NORMAL:
|
||||
typeClass = 'commit-normal';
|
||||
break;
|
||||
|
@ -111,7 +113,7 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
typeClass = 'commit-normal';
|
||||
}
|
||||
|
||||
if (commit.type === commitType.HIGHLIGHT) {
|
||||
if (commitSymbolType === commitType.HIGHLIGHT) {
|
||||
const circle = gBullets.append('rect');
|
||||
circle.attr('x', x - 10);
|
||||
circle.attr('y', y - 10);
|
||||
|
@ -135,7 +137,7 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
branchPos[commit.branch].index % THEME_COLOR_LIMIT
|
||||
} ${typeClass}-inner`
|
||||
);
|
||||
} else if (commit.type === commitType.CHERRY_PICK) {
|
||||
} else if (commitSymbolType === commitType.CHERRY_PICK) {
|
||||
gBullets
|
||||
.append('circle')
|
||||
.attr('cx', x)
|
||||
|
@ -181,7 +183,7 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
'class',
|
||||
`commit ${commit.id} commit${branchPos[commit.branch].index % THEME_COLOR_LIMIT}`
|
||||
);
|
||||
if (commit.type === commitType.MERGE) {
|
||||
if (commitSymbolType === commitType.MERGE) {
|
||||
const circle2 = gBullets.append('circle');
|
||||
circle2.attr('cx', x);
|
||||
circle2.attr('cy', y);
|
||||
|
@ -193,7 +195,7 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
}`
|
||||
);
|
||||
}
|
||||
if (commit.type === commitType.REVERSE) {
|
||||
if (commitSymbolType === commitType.REVERSE) {
|
||||
const cross = gBullets.append('path');
|
||||
cross
|
||||
.attr('d', `M ${x - 5},${y - 5}L${x + 5},${y + 5}M${x - 5},${y + 5}L${x + 5},${y - 5}`)
|
||||
|
@ -215,7 +217,12 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
const px = 4;
|
||||
const py = 2;
|
||||
// Draw the commit label
|
||||
if (commit.type !== commitType.CHERRY_PICK && gitGraphConfig.showCommitLabel) {
|
||||
if (
|
||||
commit.type !== commitType.CHERRY_PICK &&
|
||||
((commit.customId && commit.type === commitType.MERGE) ||
|
||||
commit.type !== commitType.MERGE) &&
|
||||
gitGraphConfig.showCommitLabel
|
||||
) {
|
||||
const wrapper = gLabels.append('g');
|
||||
const labelBkg = wrapper.insert('rect').attr('class', 'commit-label-bkg');
|
||||
|
||||
|
|
|
@ -121,11 +121,22 @@ cherryPickStatement
|
|||
;
|
||||
|
||||
mergeStatement
|
||||
: MERGE ID {yy.merge($2)}
|
||||
| MERGE ID COMMIT_TAG STR {yy.merge($2, $4)}
|
||||
| MERGE ID COMMIT_ID STR {yy.merge($2, '', $4)}
|
||||
| MERGE ID COMMIT_TAG STR COMMIT_ID STR {yy.merge($2, $4, $6)}
|
||||
| MERGE ID COMMIT_ID STR COMMIT_TAG STR {yy.merge($2, $6, $4)}
|
||||
: MERGE ID {yy.merge($2,'','','')}
|
||||
| MERGE ID COMMIT_ID STR {yy.merge($2, $4,'','')}
|
||||
| MERGE ID COMMIT_TYPE commitType {yy.merge($2,'', $4,'')}
|
||||
| MERGE ID COMMIT_TAG STR {yy.merge($2, '','',$4)}
|
||||
| MERGE ID COMMIT_TAG STR COMMIT_ID STR {yy.merge($2, $6,'', $4)}
|
||||
| MERGE ID COMMIT_TAG STR COMMIT_TYPE commitType {yy.merge($2, '',$6, $4)}
|
||||
| MERGE ID COMMIT_TYPE commitType COMMIT_TAG STR {yy.merge($2, '',$4, $6)}
|
||||
| MERGE ID COMMIT_ID STR COMMIT_TYPE commitType {yy.merge($2, $4, $6, '')}
|
||||
| MERGE ID COMMIT_ID STR COMMIT_TAG STR {yy.merge($2, $4, '', $6)}
|
||||
| MERGE ID COMMIT_TYPE commitType COMMIT_ID STR {yy.merge($2, $6,$4, '')}
|
||||
| MERGE ID COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.merge($2, $4, $6, $8)}
|
||||
| MERGE ID COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR {yy.merge($2, $8, $4, $6)}
|
||||
| MERGE ID COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.merge($2, $4, $8, $6)}
|
||||
| MERGE ID COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR {yy.merge($2, $6, $4, $8)}
|
||||
| MERGE ID COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.merge($2, $8, $6, $4)}
|
||||
| MERGE ID COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.merge($2, $6, $8, $4)}
|
||||
;
|
||||
|
||||
commitStatement
|
||||
|
|
Loading…
Reference in New Issue