php实现了git命令的运行
安装 git 后,在git bash里运行
getBranch(); if ($branchName == GitCommand::MERGE_BRANCH) { exit('the two branch is same.'); } if (!$branchName) { exit('can not get branch name'); } $needToCommit = $gitCommand->needCommit(); $mergeBranch = GitCommand::MERGE_BRANCH; if ($needToCommit) { echo 'Please commit before merge.' . PHP_EOL; exit; } //拉master $command = GitCommand::ORIGIN_PULL . $mergeBranch; exec($command, $pullOutput); $haveConflict = GitCommand::haveConflict($pullOutput); if ($haveConflict) { echo 'may have conflict, please solve it.' . PHP_EOL; exit; } GitCommand::checkout($mergeBranch); //origin pull $command = GitCommand::ORIGIN_PULL . $mergeBranch; exec($command, $pullOutput); $haveConflict = GitCommand::haveConflict($pullOutput); if ($haveConflict) { echo 'may have conflict, please solve it.' . PHP_EOL; exit; } //merge $command = GitCommand::MERGE . $branchName; exec($command, $mergeOutput); $haveConflict = GitCommand::haveConflict($mergeOutput); if ($haveConflict) { echo 'may have conflict, please solve it.' . PHP_EOL; exit; } //tag $lastTag = GitCommand::getTag(); if (!$lastTag) { exit('can not get the last tag.'); } if (!$description) { $description = 'default description'; } $addRes = $gitCommand->addTag($lastTag, $description); if (!$addRes) { exit('add tag fail.'); } $pushRes = GitCommand::pushToOrigin($mergeBranch, true); if (!$pushRes) { exit('push to origin ' . $mergeBranch . ' fail.'); } //回到原分支 GitCommand::checkout($branchName); $response = 'success merge&push to origin ' . $mergeBranch; $outputObj = new Output(); $outputObj->customEcho($response); class GitCommand { const PROJECT_ROOT = '/e/project'; const MERGE_BRANCH = 'master'; const BRANCH = "git branch "; const PULL = "git pull "; const ORIGIN_PULL = "git pull origin "; const PUSH = "git push "; const ORIGIN_PUSH = "git push origin "; const ORIGIN_PUSH_TAG = "git push origin BRANCH --tag"; const CHECKOUT = "git checkout "; const STATUS = 'git status'; const MERGE = 'git merge '; const FETCH_TAG = 'git fetch --tag'; const TAG_TAIL = 'git tag | tail -1'; const CONFIG_NAME = 'git config --global user.name'; const ADD_TAG = 'git tag -a TAG -m "DESCRIPTION"'; private $branch = null; private $needCommit = null; public function __construct() { exec(GitCommand::STATUS, $output); $branchName = ''; $needToCommit = false; if ($output) { //匹配所在分支 //"On branch watson-git" $branchNameRegex = '/^On branch ((\w|-){1,})$/'; //有文件改了 //有新文件 //未commit $change = 'Changes to be committed:'; $new = 'Changes not staged for commit:'; foreach ($output as $item) { if (!$branchName) { preg_match($branchNameRegex, $item, $match); $branchName = $match[1]; } if ((false !== strpos($item, $change)) || (false !== strpos($item, $new))) { $needToCommit = true; break; } } } $this->branch = $branchName; $this->needCommit = $needToCommit; } public static function checkout($branch) { $command = GitCommand::CHECKOUT . $branch; exec($command, $temp); } public static function toProjectDir() { exec('pwd', $dir); if (GitCommand::PROJECT_ROOT != $dir[0]) { exec('cd ' . GitCommand::PROJECT_ROOT, $cdLog); } } public function getBranch() { if (null === $this->branch) { exit('error, git status can not be resolved.'); } return $this->branch; } public function needCommit() { if (null === $this->needCommit) { exit('error, git status can not be resolved.'); } return $this->needCommit; } public static function haveConflict($output) { $res = false; if ($output) { $conflict = 'conflict'; foreach ($output as $item) { if (strpos($item, $conflict) > 0 || strpos($item, $conflict) === 0) { $res = true; } } } return $res; } public function addTag($lastTag, $tagDescription = '') { $name = $this->getAuthor(); if (!$name) { return false; } //解析tag if (!$lastTag) { return false; } $tagArr = explode('-', $lastTag); $project = $tagArr[0]; $versionStr = $tagArr[1]; $time = date('YmdHi'); $versionArr = explode('.', $versionStr); $versionNum = implode('', $versionArr); $versionNum++; $versionArr = str_split($versionNum); $versionStr = implode('.', $versionArr); if (!$project || !$versionStr || !$time || !$name) { return false; } $newTagArr = array($project, $versionStr, $time, $name); $newTag = implode('-', $newTagArr); $command = str_replace('TAG', $newTag, self::ADD_TAG); $command = str_replace('DESCRIPTION', $tagDescription, $command); exec($command, $addOutput); return true; } private function getAuthor() { $name = ''; exec(self::CONFIG_NAME, $output); if ($output) { $fullName = $output[0]; $arr = explode('.', $fullName); $name = $arr[0]; } return $name; } public static function getTag() { exec(self::FETCH_TAG, $output); exec(self::TAG_TAIL, $output); $lastTag = ''; if ($output) { $lastTag = array_pop($output); } return $lastTag; } public static function pushToOrigin($branch, $withTag = false) { if ($withTag) { $command = str_replace('BRANCH', $branch, GitCommand::ORIGIN_PUSH_TAG); } else { $command = GitCommand::ORIGIN_PUSH . $branch; } exec($command, $pushOutput); if ($pushOutput) { foreach ($pushOutput as $item) { $pos = strpos($item, 'hint'); if ($pos > 0 || 0 === $pos) { return false; } } } return true; } } class Output { public function customEcho($str) { $middle = '****** ' . $str . ' ******'; $len = strlen($middle); $this->printStar($len); echo $middle . PHP_EOL; $this->printStar($len); } private function printStar($len) { for ($i = 0; $i < $len; $i++) { echo "*"; } echo PHP_EOL; } }