docs: function Commit(relLbl, relType, relRx, bumpRx, cmo, pver, nver, gitCliSubstitute, ch, pkgPath, pkgPathBower,
  		pkgPropSync, buildDir, branch, slug, username, reponame, gitToken, npmToken) {
  	var cm = typeof cmo === 'string' ? cmo : cmo.message;
  	this.versionRegExp = typeof cmo === 'object' && cmo.matcher ? cmo.matcher : relRx;
  	var rv = cm.match(this.versionRegExp);
  	if ((!rv || !rv.length) && typeof cmo === 'object' && typeof cmo.altMessage === 'string') {
  		cm = cmo.altMessage;
  		this.versionRegExp = cmo.altMatcher || cmo.matcher;
  		rv = cm.match(this.versionRegExp);
  	}
  	if (!rv) {
  
  		rv = [];
  	}
  	var self = this;
  	var vt = 0, si = -1;
  	this.gitCliSubstitute = gitCliSubstitute;
  	this.pkgPath = pkgPath;
  	this.pkgPathBower = pkgPathBower;
  	this.pkgPropSync = pkgPropSync;
  	this.hash = ch;
  	this.buildDir = buildDir;
  	this.branch = branch;
  	this.slug = slug;
  	this.username = username;
  	this.reponame = reponame;
  	this.gitToken = gitToken || '';
  	this.npmToken = npmToken || '';
  	this.releaseId = null;
  	this.releaseAssets = [];
  	this.skipTasks = [];
  	this.skipTaskGen = function() {
  		return committer.skipTaskGen(false, Array.prototype.slice.call(arguments, 0));
  	};
  	this.skipTaskCheck = function(task) {
  		return self.skipTasks && self.skipTasks.indexOf(task) >= 0;
  	};
  	if (cm) {
  		// extract skip tasks in format: [skip someTask]
  		cm.replace(regexSkips, function(m, t) {
  			self.skipTasks.push(t);
  		});
  	}
  	this.hasGitToken = typeof gitToken === 'function' ? gitToken().length > 0 : typeof gitToken === 'string'
  			&& gitToken.length > 0;
  	this.hasNpmToken = typeof npmToken === 'function' ? npmToken().length > 0 : typeof npmToken === 'string'
  			&& npmToken.length > 0;
  	this.message = cm;
  	this.versionMatch = rv;
  	this.versionBumpedIndices = [];
  	this.versionPrevIndices = [];
  	this.versionVacant = function() {
  		return isNaN(this.versionMajor) && isNaN(this.versionMinor) && isNaN(this.versionPatch)
  				&& !this.versionPrerelease;
  	};
  	this.versionLabel = rv.length > 1 ? rv[1] : '';
  	this.versionLabelSep = rv.length > 2 ? rv[2] : '';
  	this.versionType = rv.length > 3 ? rv[3] : '';
  	this.prev = pver instanceof Commit ? pver : typeof pver === 'string' ? new Commit(relLbl, relType, relRx, bumpRx,
  			(self.versionLabel || relLbl) + (self.versionLabelSep || ' ') + (self.versionType || relType) + pver, null,
  			self) : {
  		version : '0.0.0',
  		versionMatch : []
  	};
  	this.versionPrereleaseChar = rv.length > 10 ? rv[10] : '';
  	this.versionMajor = rv.length > 5 ? verMatchVal(5) : 0;
  	this.versionMinor = rv.length > 7 ? verMatchVal(7) : 0;
  	this.versionPatch = rv.length > 9 ? verMatchVal(9) : 0;
  	var versionSuffix = verSuffix(11);
  	this.versionPrerelease = versionSuffix.prerelease;
  	this.versionMetadata = versionSuffix.metadata;
  	this.version = this.versionPrevIndices.length || this.versionBumpedIndices.length ? vver() : rv.length > 4 ? rv[4]
  			: '';
  	this.versionTag = rv.length > 4 ? rv[3] + this.version : '';
  	this.versionTrigger = vmtchs(1, 11, [ 4 ]);
  	this.versionPkg = function(opts, cb) {
  		var pth = opts.altPkgPath || self.pkgPath || pkgPath;
  		var pthb = opts.altPkgPathBower || self.pkgPathBower || pkgPathBower;
  		var pkgp = self.pkgPropSync || pkgPropSync;
  		// update package (if needed)
  		var pd = pkgUpdate(pth);
  		// update bower package when any of the sync properties do not match
  		// what's in the master package
  		var pdb = pkgUpdate(pthb, pd, pkgp);
  		if (typeof cb === 'function') {
  			cb(pd, pdb);
  		}
  		return {
  			pkg : pd,
  			pkgBower : pdb
  		};
  		// updates a package for a given path, parent package data (from
  		// previous call to same function)
  		// an optional array of properties to match can be passed that will be
  		// matched against the parent package
  		function pkgUpdate(pth, prt, props) {
  			var rtn = {
  				path : pth || '',
  				props : Array.isArray(props) ? props : null,
  				oldVer : '',
  				version : '',
  				propChangeCount : 0
  			};
  			if (!rtn.path) {
  				return rtn;
  			}
  			rtn.pkg = rbot.file.readJSON(rtn.path);
  			rtn.pkgParent = prt;
  			rtn.oldVer = rtn.pkg.version;
  			rtn.u = !opts.revert && !opts.next && pkgPropUpd(rtn, true, false, false);
  			rtn.n = !opts.revert && opts.next && pkgPropUpd(rtn, false, true, false);
  			rtn.r = opts.revert && pkgPropUpd(rtn, false, false, true);
  			if (rtn.u || rtn.n || rtn.r) {
  				if (rtn.propChangeCount > 0) {
  					rtn.pkgStr = JSON.stringify(rtn.pkg, opts.replacer, opts.space);
  					if (!opts.readOnly) {
  						rbot.file.write(rtn.path, typeof opts.altWrite === 'function' ? opts.altWrite(rtn,
  								opts.replacer, opts.space) : rtn.pkgStr);
  					}
  				}
  			}
  			return rtn;
  		}
  		// updates the package version or a set of properties from a parent
  		// package for a given package data element and flag
  		function pkgPropUpd(pd, u, n, r) {
  			var v = null;
  			if (u && pd.oldVer !== self.version && self.version) {
  				v = self.version;
  			} else if (n && pd.oldVer !== self.next.version && self.next.version) {
  				v = self.next.version;
  			} else if (r && self.prev.version) {
  				v = self.prev.version;
  			}
  			pd.version = v;
  			if (v && !pd.props) {
  				pd.pkg.version = v;
  				pd.propChangeCount++;
  			}
  			if (pd.props && pd.pkgParent) {
  				pd.props.forEach(function pkgProp(p) {
  					if (pd.pkgParent[p] && (!pd.pkg[p] || pd.pkgParent[p] !== pd.pkg[p])) {
  						// sync parent package property with the current one
  						pd.pkg[p] = pd.pkgParent[p];
  						pd.propChangeCount++;
  					}
  				});
  			}
  			return v;
  		}
  	};
  	this.versionValidate = function() {
  		if (!validate(self.version)) {
  			return false;
  		} else if (self.prev.version && semver.gte(self.prev.version, self.version)) {
  			throw new Error(self.version + ' must be higher than the previous release version ' + self.prev.version);
  		} else if (self.next.version && semver.lte(self.next.version, self.version)) {
  			throw new Error(self.version + ' must be lower than the next release version ' + self.next.version);
  		}
  		return true;
  	};
  	this.next = nver === true && this.version ? new Commit(relLbl, relType, relRx, bumpRx, {
  		matcher : bumpRx,
  		message : cm,
  		altMatcher : relRx,
  		altMessage : (self.versionLabel || relLbl) + (self.versionLabelSep || ' ') + vver(true, true)
  	}, self) : nver instanceof Commit ? nver : {
  		version : ''
  	};
  	function validate(v, q) {
  		if (!v) {
  			if (!q) {
  				rbot.log.verbose('Non-release commit ' + (v || ''));
  			}
  			return false;
  		} else if (!self.hasGitToken) {
  			throw new Error('No Git token found, version: ' + v);
  		} else if (!semver.valid(v)) {
  			throw new Error('Invalid release version: ' + v);
  		}
  		return true;
  	}
  	// parse out bump/current version characters from version slot
  	function verMatchVal(i) {
  		var v = self.versionMatch[i];
  		var vr = 0;
  		var vl = self.prev.versionMatch && self.prev.versionMatch.length > i && self.prev.versionMatch[i] ? +self.prev.versionMatch[i]
  				: vr;
  		si++;
  		// reset the last index so the tests will be accurate
  		regexVerBump.lastIndex = 0;
  		regexVerCurr.lastIndex = 0;
  		if (v && regexVerBump.test(v)) {
  			// increment the value for the given slot
  			self.versionBumpedIndices.push(si);
  			var bcnt = 0;
  			v.replace(regexVerBump, function vBump(m) {
  				bcnt += m.length;
  			});
  			vr = vl + bcnt;
  		} else if (v && regexVerCurr.test(v)) {
  			// use the last release value for the given slot
  			self.versionPrevIndices.push(si);
  			vr = vl;
  		} else if (v) {
  			// faster parseInt using unary operator
  			vr = +v;
  		}
  		vt += vr;
  		return vr;
  	}
  	// parse out bump/current version characters from prerelease/metadata
  	function verSuffix(i) {
  		var rtn = {
  			prerelease : '',
  			metadata : '',
  			prereleaseVersions : null
  		};
  		if (self.versionMatch.length <= i) {
  			return rtn;
  		}
  		var v = self.versionMatch[i];
  		// reset the last index so the tests will be accurate
  		regexVerCurrBumpNum.lastIndex = 0;
  		// replace place holders with current or bumped version
  		var vi = -1;
  		var pvers = self.prev && self.prev.versionPrerelease && self.prev.versionPrerelease.match(regexVerNum);
  		var mdi = v.lastIndexOf(charVerMeta);
  		var lsti = v.length - 1;
  		v = v.replace(regexVerCurrBumpNum, function verCurrRepl(m, cg, bg, ng, off) {
  			vi++;
  			if (ng) {
  				return m;
  			}
  			if (cg) {
  				// match previous rerelease version slots with the current place
  				// holder slot (if any)
  				self.versionPrevIndices.push(++si);
  				return pvers && pvers.length > vi ? pvers[vi] : 0;
  			} else if (bg) {
  				// only increment when the bump is not the last instance or is
  				// the last instance, but there is metadata following its
  				// occurrence
  				if (mdi === lsti || mdi !== off || (off + m.length - 1) === lsti) {
  					self.versionBumpedIndices.push(++si);
  					return (pvers && pvers.length > vi ? +pvers[vi] : 0) + m.length;
  				}
  			}
  			return m;
  		});
  		// separate metadata from the prerelease
  		mdi = v.indexOf(charVerMeta);
  		if (mdi >= 0) {
  			rtn.prerelease = mdi === 0 ? '' : v.substring(0, mdi);
  			rtn.metadata = v.substring(mdi);
  		} else {
  			rtn.prerelease = v;
  		}
  		return rtn;
  	}
  	// reconstruct version w/optional incrementation
  	function vver(pt, inc) {
  		return (pt ? vv(3) : '') + vv(5, self.versionMajor) + vv(6) + vv(7, self.versionMinor) + vv(8)
  				+ vv(9, self.versionPatch, inc && !self.versionPrereleaseChar) + vv(10)
  				+ vv(11, self.versionPrerelease, inc && self.versionPrereleaseChar) + vv(12, self.versionMetadata);
  	}
  	// gets a version slot based upon a match index or passed value w/optional
  	// incrementation
  	function vv(i, v, inc) {
  		var vn = !isNaN(v);
  		var nv = vn ? v : v || self.versionMatch[i] || '';
  		if (inc && vn) {
  			return +nv + 1;
  		} else if (inc) {
  			// increment the last numeric value sequence
  			return nv.replace(regexVerLast, function vvInc(m) {
  				return +m + 1;
  			});
  		}
  		return nv;
  	}
  	// reconstructs the version matches
  	function vmtchs(start, end, skips) {
  		var s = '';
  		for (var i = start; i <= end; i++) {
  			if (skips && skips.indexOf(i) >= 0) {
  				continue;
  			}
  			s += self.versionMatch[i] || '';
  		}
  		return s;
  	}
  }