这个脚本的目的就是一次性批量更新当前目录的全部.git项目,很多时候一到公司就需要同步N个仓库往往来不及,于是写个脚本提升工作效率。
<?php
declare(strict_types=1);//默认严格模式
$readDir = function($dir, $maxDepth) use (&$readDir) {
if($maxDepth < 1) {
return [];
}
$list = [];
if($handle = opendir($dir)) {
while(($name = readdir($handle)) !== false) {
if($name == "." || $name == "..") {
continue;
}
$path = $dir.DIRECTORY_SEPARATOR.$name;
if(is_dir($path)) {
$list[] = $path;
}
}
closedir($handle);
}
$result = [];
foreach($list as $item) {
$baseName = basename($item);
if($baseName === ".git") {
$result[] = dirname($item);
} else {
$result = array_merge($result, $readDir($item, $maxDepth - 1));
}
}
return $result;
};
$log = function(string $log) {
echo "[".date("Y-m-d H:i:s")."]{$log}", PHP_EOL;
};
$dir = $argv[1] ?? null;
if(!empty($dir)) {
if(!is_dir($dir)) {
$log("目录不存在: {$dir}");
exit(1);
}
} else {
$dir = __DIR__;
}
$dir = realpath($dir);
$log("读取目录: {$dir}");
$list = $readDir($dir, 4);
$log("读取GIT列表: ".count($list));
$updateGit = function($path) use (&$log) {
$shell_exec_passthru = function($shell) use (&$log) {
$log($shell);
passthru($shell);
};
chdir($path);
$branch_text = shell_exec("git branch");
$branch_list = array_values(array_filter(array_map(function($a) {
return trim($a);
}, explode("\n", $branch_text))));
if(empty($branch_list)) {
$log("无任何分支需要更新");
return;
}
$branch_list = (function($branch_list) {
$list = [];
$listTop = [];
foreach($branch_list as $branch) {
if($branch[0] == "*") {
$listTop[] = trim(substr($branch, 1));
} else {
$list[] = $branch;
}
}
return array_merge($listTop, $list);
})($branch_list);
$currentBranch = $branch_list[0];
$log(sprintf("当前分支: %s", $currentBranch));
$log(sprintf("全部分支列表: %s", PHP_EOL."----".implode(PHP_EOL."----", $branch_list)));
$fetch_all = "git fetch --all -p";
$log("更新全部分支: {$fetch_all}");
$shell_exec_passthru($fetch_all);
$behind_branch_list = (function() use (&$log) {
$branch_info = shell_exec("git branch -v");
$branch_info = array_map(function($v) {
$v = trim($v);
$v = trim($v, "*");
$v = trim($v);
$v = preg_replace("/[\s]{2,}/", " ", $v);
$v = explode(" ", $v, 3);
return $v;
}, explode("\n", trim($branch_info)));
$result = [];
foreach($branch_info as $item) {
if(empty($item)) {
continue;
}
if(!isset($item[2])) {
continue;
}
if(preg_match("/^\\[behind ([\\d]+)\\]/", $item[2], $match) > 0) {
$log("{$item[0]}, behind: {$match[1]}");
$result[] = $item[0];
}
}
return $result;
})();
//依旧使用多个分支单独推送,由于每个分支可能会有更新
$lastBranch = null;
foreach($branch_list as $branch) {
if(empty($branch)) {
continue;
}
if(in_array($branch, $behind_branch_list)) {
$shell_exec_passthru("git checkout {$branch}");
$shell_exec_passthru("git pull origin");
$lastBranch = $branch;
}
}
if(!empty($lastBranch) && $lastBranch != $currentBranch) {
$shell_exec_passthru("git checkout {$currentBranch}");
}
// $shell_exec_passthru("git checkout master");
};
$count = count($list);
foreach($list as $i => $path) {
echo PHP_EOL, PHP_EOL;
$log(sprintf("准备更新: %s, %d/%d", $path, $i + 1, $count));
$updateGit($path);
}
declare(strict_types=1);//默认严格模式
$readDir = function($dir, $maxDepth) use (&$readDir) {
if($maxDepth < 1) {
return [];
}
$list = [];
if($handle = opendir($dir)) {
while(($name = readdir($handle)) !== false) {
if($name == "." || $name == "..") {
continue;
}
$path = $dir.DIRECTORY_SEPARATOR.$name;
if(is_dir($path)) {
$list[] = $path;
}
}
closedir($handle);
}
$result = [];
foreach($list as $item) {
$baseName = basename($item);
if($baseName === ".git") {
$result[] = dirname($item);
} else {
$result = array_merge($result, $readDir($item, $maxDepth - 1));
}
}
return $result;
};
$log = function(string $log) {
echo "[".date("Y-m-d H:i:s")."]{$log}", PHP_EOL;
};
$dir = $argv[1] ?? null;
if(!empty($dir)) {
if(!is_dir($dir)) {
$log("目录不存在: {$dir}");
exit(1);
}
} else {
$dir = __DIR__;
}
$dir = realpath($dir);
$log("读取目录: {$dir}");
$list = $readDir($dir, 4);
$log("读取GIT列表: ".count($list));
$updateGit = function($path) use (&$log) {
$shell_exec_passthru = function($shell) use (&$log) {
$log($shell);
passthru($shell);
};
chdir($path);
$branch_text = shell_exec("git branch");
$branch_list = array_values(array_filter(array_map(function($a) {
return trim($a);
}, explode("\n", $branch_text))));
if(empty($branch_list)) {
$log("无任何分支需要更新");
return;
}
$branch_list = (function($branch_list) {
$list = [];
$listTop = [];
foreach($branch_list as $branch) {
if($branch[0] == "*") {
$listTop[] = trim(substr($branch, 1));
} else {
$list[] = $branch;
}
}
return array_merge($listTop, $list);
})($branch_list);
$currentBranch = $branch_list[0];
$log(sprintf("当前分支: %s", $currentBranch));
$log(sprintf("全部分支列表: %s", PHP_EOL."----".implode(PHP_EOL."----", $branch_list)));
$fetch_all = "git fetch --all -p";
$log("更新全部分支: {$fetch_all}");
$shell_exec_passthru($fetch_all);
$behind_branch_list = (function() use (&$log) {
$branch_info = shell_exec("git branch -v");
$branch_info = array_map(function($v) {
$v = trim($v);
$v = trim($v, "*");
$v = trim($v);
$v = preg_replace("/[\s]{2,}/", " ", $v);
$v = explode(" ", $v, 3);
return $v;
}, explode("\n", trim($branch_info)));
$result = [];
foreach($branch_info as $item) {
if(empty($item)) {
continue;
}
if(!isset($item[2])) {
continue;
}
if(preg_match("/^\\[behind ([\\d]+)\\]/", $item[2], $match) > 0) {
$log("{$item[0]}, behind: {$match[1]}");
$result[] = $item[0];
}
}
return $result;
})();
//依旧使用多个分支单独推送,由于每个分支可能会有更新
$lastBranch = null;
foreach($branch_list as $branch) {
if(empty($branch)) {
continue;
}
if(in_array($branch, $behind_branch_list)) {
$shell_exec_passthru("git checkout {$branch}");
$shell_exec_passthru("git pull origin");
$lastBranch = $branch;
}
}
if(!empty($lastBranch) && $lastBranch != $currentBranch) {
$shell_exec_passthru("git checkout {$currentBranch}");
}
// $shell_exec_passthru("git checkout master");
};
$count = count($list);
foreach($list as $i => $path) {
echo PHP_EOL, PHP_EOL;
$log(sprintf("准备更新: %s, %d/%d", $path, $i + 1, $count));
$updateGit($path);
}
这个很有用,一堆GIt库代码一个个更新太麻烦~感谢分享。。。弱弱问句,这个在windows上怎么运行呢
php syncBranch.php
当前目录执行
看得眼睛疼,看懂了50%
厉害