admin管理员组

文章数量:1530057

git commit message 标准化--Ubuntu安装commitizen工具

    • 安装npm
    • 安装node
    • 安装commitizen
    • 安装conventional-changelog(非必须)
    • 配置适配器
    • 测试一下
    • 改进

安装npm

sudo apt-get install npm

安装node

node不要安装最新版本,不然会报warning,确认8.10.0版本是没什么问题的

sudo npm install -g n
sudo n 8.10.0

安装commitizen

sudo npm install -g commitizen

安装conventional-changelog(非必须)

sudo npm install -g conventional-changelog

这个工具是用来自动生成CHANGELOG.md文件

使用的方法是在git工程目录下执行类似如下命令:

conventional-changelog -p angular -i CHANGELOG.md -s -r 0

配置适配器

网上很多的教程使用如下命令:

commitizen init cz-conventional-changelog --save-dev --save-exact

此命令是在git工程目录下执行的,会生成package.json文件,且只在此git工程有效,新的git工程要重新执行

推荐的做法是配置全局的
如果是当前用户有效

echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

或所有用户有效

echo '{ "path": "cz-conventional-changelog" }' > /.czrc

测试一下

tester@Server:~/Git_Proj$ git cz
cz-cli@4.0.4, cz-conventional-changelog@3.0.1

? Select the type of change that you're committing: (Use arrow keys)
❯ feat:        A new feature
  fix:         A bug fix
  improvement: An improvement to a current feature
  docs:        Documentation only changes
  style:       Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  refactor:    A code change that neither fixes a bug nor adds a feature
  perf:        A code change that improves performance
(Move up and down to reveal more choices)

改进

虽然作为程序员这点英文还是可以看的懂的,但看中文还是要舒服点。而且有些交互方式不是很适合自己,所以对交互脚本进行了魔改。
主要改进了三点:

  1. 汉化处理。
  2. 原来的长文本编辑只能使用\n符号换行,排版不够直观,所以改成跳转到编辑器编写。
  3. BREAKING CHANGE 的逻辑上感觉有点乱,调整了交互逻辑。

修改index.json 替换 /usr/local/lib/node_modules/commitizen/node_modules/conventional-commit-types/index.json

{
  "types": {
    "feat": {
      "description": "添加新功能",
      "title": "Features"
    },
    "fix": {
      "description": "修复bug缺陷",
      "title": "Bug Fixes"
    },
    "improvement": {
      "description": "修改现有功能",
      "title": "Improvements"
    },
    "docs": {
      "description": "变更文档",
      "title": "Documentation"
    },
    "style": {
      "description": "调整代码格式,未有功能代码修改(例如:空白字符宽度、对齐、添加分隔符、注释)",
      "title": "Styles"
    },
    "refactor": {
      "description": "重构代码,未涉及新功能或缺陷修复",
      "title": "Code Refactoring"
    },
    "perf": {
      "description": "优化性能",
      "title": "Performance Improvements"
    },
    "test": {
      "description": "新增或修改测试代码",
      "title": "Tests"
    },
    "build": {
      "description": "修改构建系统或外部依赖(例如:gulp, broccoli, npm)",
      "title": "Builds"
    },
    "ci": {
      "description": "修改自动化构建脚本 (例如: Travis, Circle, BrowserStack, SauceLabs)",
      "title": "Continuous Integrations"
    },
    "chore": {
      "description": "其它非代码或测试的变更",
      "title": "Chores"
    },
    "revert": {
      "description": "恢复到上一次commit提交",
      "title": "Reverts"
    }
  }
}

修改engine.js 替换 /usr/local/lib/node_modules/commitizen/node_modules/cz-conventional-changelog/engine.js

'format cjs';

var wrap = require('word-wrap');
var map = require('lodash.map');
var longest = require('longest');
var rightPad = require('right-pad');
var chalk = require('chalk');

var filter = function(array) {
  return array.filter(function(x) {
    return x;
  });
};

var headerLength = function(answers) {
  return (
    answers.type.length + 2 + (answers.scope ? answers.scope.length + 2 : 0)
  );
};

var maxSummaryLength = function(options, answers) {
  return options.maxHeaderWidth - headerLength(answers);
};

var filterSubject = function(subject) {
  subject = subject.trim();
  if (subject.charAt(0).toLowerCase() !== subject.charAt(0)) {
    subject =
      subject.charAt(0).toLowerCase() + subject.slice(1, subject.length);
  }
  while (subject.endsWith('.')) {
    subject = subject.slice(0, subject.length - 1);
  }
  return subject;
};

// This can be any kind of SystemJS compatible module.
// We use Commonjs here, but ES6 or AMD would do just
// fine.
module.exports = function(options) {
  var types = options.types;

  var length = longest(Object.keys(types)).length + 1;
  var choices = map(types, function(type, key) {
    return {
      name: rightPad(key + ':', length) + ' ' + type.description,
      value: key
    };
  });

  return {
    // When a user runs `git cz`, prompter will
    // be executed. We pass you cz, which currently
    // is just an instance of inquirer.js. Using
    // this you can ask questions and get answers.
    //
    // The commit callback should be executed when
    // you're ready to send back a commit template
    // to git.
    //
    // By default, we'll de-indent your commit
    // template and will keep empty lines.
    prompter: function(cz, commit) {
      // Let's ask some questions of the user
      // so that we can populate our commit
      // template.
      //
      // See inquirer.js docs for specifics.
      // You can also opt to use another input
      // collection library if you prefer.
      cz.prompt([
        {
          type: 'list',
          name: 'type',
          message: "请选择commit类型:",
          choices: choices,
          default: options.defaultType
        },
        {
          type: 'input',
          name: 'scope',
          message:
            '此修改的影响范围[选填](Enter键跳过):',
          default: options.defaultScope,
          filter: function(value) {
            return value.trim().toLowerCase();
          }
        },
        {
          type: 'input',
          name: 'subject',
          message: function(answers) {
            return (
              '请简要描述修改内容[必填](不超过' +
              maxSummaryLength(options, answers) +
              '个字符):\n'
            );
          },
          default: options.defaultSubject,
          validate: function(subject, answers) {
            var filteredSubject = filterSubject(subject);
            return filteredSubject.length == 0
              ? '必须填写描述'
              : filteredSubject.length <= maxSummaryLength(options, answers)
              ? true
              : '描述需小于或等于 ' +
                maxSummaryLength(options, answers) +
                ' 个字符. 当前输入了 ' +
                filteredSubject.length +
                ' 个字符.';
          },
          transformer: function(subject, answers) {
            var filteredSubject = filterSubject(subject);
            var color =
              filteredSubject.length <= maxSummaryLength(options, answers)
                ? chalk.green
                : chalk.red;
            return color('(' + filteredSubject.length + ') ' + subject);
          },
          filter: function(subject) {
            return filterSubject(subject);
          }
        },
        {
          type: 'confirm',
          name: 'isBoding',
          message:
                '是否需要详细描述修改内容?\n',
          default: false
        },
        {
          type: 'editor',
          name: 'body',
          message:
            '请详细描述修改内容:\n',
          when: function(answers) {
            return answers.isBoding;
          },
          default: options.defaultBody
        },
        {
          type: 'confirm',
          name: 'isBreaking',
          message: '此修改不兼容旧版本?',
          default: false
        },
        {
          type: 'editor',
          name: 'breaking',
          message: '请详细描述不兼容的内容:\n',
          when: function(answers) {
            return answers.isBreaking;
          }
        },

        {
          type: 'input',
          name: 'issues',
          message: '请填写对应的问题或需求编号[选填] (例如:"fix #123".):\n',
          default: options.defaultIssues ? options.defaultIssues : undefined
        }
      ]).then(function(answers) {
        var wrapOptions = {
          trim: true,
          cut: false,
          newline: '\n',
          indent: '',
          width: options.maxLineWidth
        };

        // parentheses are only needed when a scope is present
        var scope = answers.scope ? '(' + answers.scope + ')' : '';

        // Hard limit this line in the validate
        var head = answers.type + scope + ': ' + answers.subject;

        // Wrap these lines at options.maxLineWidth characters
        var body = answers.body ? wrap(answers.body, wrapOptions) : false;

        // Apply breaking change prefix, removing it if already present
        var breaking = answers.breaking ? answers.breaking.trim() : '';
        breaking = breaking
          ? 'BREAKING CHANGE: \n' + breaking.replace(/^BREAKING CHANGE: /, '')
          : '';
        breaking = breaking ? wrap(breaking, wrapOptions) : false;

        var issues = answers.issues ? wrap(answers.issues, wrapOptions) : false;

        commit(filter([head, body, breaking, issues]).join('\n\n'));
      });
    }
  };
};

再测试下

tester@Server:~/Git_Proj$ git cz
cz-cli@4.0.4, cz-conventional-changelog@3.0.1

? 请选择commit类型: (Use arrow keys)
❯ feat:        添加新功能
  fix:         修复bug缺陷
  improvement: 修改现有功能
  docs:        变更文档
  style:       调整代码格式,未有功能代码修改(例如:空白字符宽度、对齐、添加分隔符、注释)
  refactor:    重构代码,未涉及新功能或缺陷修复
  perf:        优化性能
(Move up and down to reveal more choices)

本文标签: 工具commitGitMessagecommitizen