fe-build-cli 1.1.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/src/cli.js +110 -37
- package/src/git-branch.js +254 -1
- package/src/index.js +4 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fe-build-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "前端项目打包部署 CLI
|
|
3
|
+
"version": "1.2.2",
|
|
4
|
+
"description": "前端项目打包部署 CLI 工具,支持多服务器部署、分支管理、回滚、钉钉通知、智能处理本地改动等功能",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"build",
|
|
28
28
|
"ssh",
|
|
29
29
|
"git",
|
|
30
|
-
"dingtalk"
|
|
30
|
+
"dingtalk",
|
|
31
|
+
"stash"
|
|
31
32
|
],
|
|
32
33
|
"author": "",
|
|
33
34
|
"license": "MIT",
|
package/src/cli.js
CHANGED
|
@@ -11,7 +11,9 @@ import {
|
|
|
11
11
|
getGitSha,
|
|
12
12
|
executeMainBranchFlow,
|
|
13
13
|
executeCurrentBranchFlow,
|
|
14
|
-
|
|
14
|
+
executeTestBranchFlow,
|
|
15
|
+
restoreBranch,
|
|
16
|
+
stashPop
|
|
15
17
|
} from './git-branch.js';
|
|
16
18
|
import {
|
|
17
19
|
sendDeploySuccessNotification,
|
|
@@ -169,13 +171,19 @@ fe-build-cli - 前端项目打包部署工具
|
|
|
169
171
|
--config <路径> 指定配置文件路径
|
|
170
172
|
--current-branch 使用当前分支发布(不切换分支)
|
|
171
173
|
--main-branch 使用主分支发布流程(合并到测试分支再合并到主分支)
|
|
174
|
+
--test-branch 使用 test 环境发布流程(智能处理本地改动)
|
|
175
|
+
--merge test 发布时合并本地改动(提交+推送+合并)
|
|
176
|
+
--no-merge test 发布时不合并,使用 stash 储藏本地改动
|
|
172
177
|
--skip-build 跳过构建步骤
|
|
173
|
-
--no-push
|
|
178
|
+
--no-push 发布时不推送到远程
|
|
174
179
|
|
|
175
180
|
示例:
|
|
176
181
|
fe-build # 交互式选择环境部署
|
|
177
182
|
fe-build deploy production # 部署到生产环境
|
|
178
|
-
fe-build deploy
|
|
183
|
+
fe-build deploy test # 部署到测试环境(使用配置的 deployMode)
|
|
184
|
+
fe-build --test-branch # test 环境发布(智能处理本地改动)
|
|
185
|
+
fe-build --test-branch --merge # test 发布,合并本地改动
|
|
186
|
+
fe-build --test-branch --no-merge # test 发布,stash 储藏改动
|
|
179
187
|
fe-build --current-branch # 当前分支发布
|
|
180
188
|
fe-build --main-branch # 主分支发布流程
|
|
181
189
|
fe-build rollback production # 回滚生产环境
|
|
@@ -222,13 +230,18 @@ async function deployCommand(config) {
|
|
|
222
230
|
const args = process.argv.slice(2);
|
|
223
231
|
const useCurrentBranch = args.includes('--current-branch');
|
|
224
232
|
const useMainBranch = args.includes('--main-branch');
|
|
233
|
+
const useTestBranch = args.includes('--test-branch');
|
|
234
|
+
const useMerge = args.includes('--merge');
|
|
235
|
+
const useNoMerge = args.includes('--no-merge');
|
|
225
236
|
const skipBuild = args.includes('--skip-build');
|
|
226
237
|
const noPush = args.includes('--no-push');
|
|
227
238
|
|
|
228
239
|
// 确定发布模式
|
|
229
240
|
let deployMode = config.deployMode || 'main'; // 默认主分支发布
|
|
230
241
|
|
|
231
|
-
if (
|
|
242
|
+
if (useTestBranch) {
|
|
243
|
+
deployMode = 'test';
|
|
244
|
+
} else if (useCurrentBranch) {
|
|
232
245
|
deployMode = 'current';
|
|
233
246
|
} else if (useMainBranch) {
|
|
234
247
|
deployMode = 'main';
|
|
@@ -268,35 +281,84 @@ async function deployCommand(config) {
|
|
|
268
281
|
|
|
269
282
|
// 执行分支发布流程
|
|
270
283
|
let branchResult = null;
|
|
271
|
-
let originalBranch =
|
|
284
|
+
let originalBranch = getCurrentBranch(); // 记录原始分支
|
|
285
|
+
let needRestore = false;
|
|
286
|
+
let hasStash = false;
|
|
287
|
+
let autoRestore = false; // 是否自动切回(合并模式)
|
|
272
288
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
289
|
+
// 分支流程(Git 操作)
|
|
290
|
+
try {
|
|
291
|
+
if (deployMode === 'test' && !skipBuild) {
|
|
292
|
+
// test 环境发布模式(智能处理本地改动)
|
|
293
|
+
const branches = config.branches || { test: 'test', main: 'main' };
|
|
294
|
+
|
|
295
|
+
// 确定合并选项
|
|
296
|
+
let mergeChanges = undefined;
|
|
297
|
+
if (useMerge) {
|
|
298
|
+
mergeChanges = true;
|
|
299
|
+
} else if (useNoMerge) {
|
|
300
|
+
mergeChanges = false;
|
|
301
|
+
}
|
|
282
302
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
303
|
+
branchResult = await executeTestBranchFlow({
|
|
304
|
+
testBranch: branches.test,
|
|
305
|
+
mergeChanges,
|
|
306
|
+
pushToRemote: !noPush,
|
|
307
|
+
prompt
|
|
308
|
+
});
|
|
309
|
+
originalBranch = branchResult.originalBranch;
|
|
310
|
+
needRestore = branchResult.needRestore;
|
|
311
|
+
hasStash = branchResult.hasStash;
|
|
312
|
+
autoRestore = branchResult.autoRestore || false;
|
|
313
|
+
} else if (deployMode === 'main' && !skipBuild) {
|
|
314
|
+
// 主分支发布模式
|
|
315
|
+
const branches = config.branches || { test: 'test', main: 'main' };
|
|
316
|
+
console.log('\n========================================');
|
|
317
|
+
console.log(' 🌿 主分支发布模式');
|
|
318
|
+
console.log('========================================');
|
|
319
|
+
console.log(`测试分支: ${branches.test}`);
|
|
320
|
+
console.log(`主分支: ${branches.main}`);
|
|
321
|
+
console.log('========================================');
|
|
322
|
+
|
|
323
|
+
const confirmAnswer = await prompt('确认执行主分支发布流程? (y/n): ');
|
|
324
|
+
if (confirmAnswer.toLowerCase() !== 'y') {
|
|
325
|
+
console.log('已取消发布');
|
|
326
|
+
process.exit(0);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
branchResult = executeMainBranchFlow({
|
|
330
|
+
testBranch: branches.test,
|
|
331
|
+
mainBranch: branches.main,
|
|
332
|
+
pushToRemote: !noPush
|
|
333
|
+
});
|
|
334
|
+
originalBranch = branchResult.originalBranch;
|
|
335
|
+
needRestore = true;
|
|
336
|
+
} else if (deployMode === 'current') {
|
|
337
|
+
// 当前分支发布模式
|
|
338
|
+
branchResult = executeCurrentBranchFlow();
|
|
339
|
+
originalBranch = branchResult.currentBranch;
|
|
340
|
+
needRestore = false;
|
|
341
|
+
console.log('📌 当前分支发布模式:不切换分支');
|
|
287
342
|
}
|
|
343
|
+
} catch (branchError) {
|
|
344
|
+
// 分支流程失败,发送钉钉通知
|
|
345
|
+
console.error(`❌ 分支流程失败:`, branchError.message);
|
|
288
346
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
347
|
+
if (config.dingtalk && config.dingtalk.enabled && config.dingtalk.webhook) {
|
|
348
|
+
console.log('\n发送钉钉失败通知...');
|
|
349
|
+
const envConfig = getServerConfig(config, selectedServers[0] || serverNames[0]);
|
|
350
|
+
await sendDeployFailureNotification(config.dingtalk.webhook, {
|
|
351
|
+
environment: selectedServers[0] || serverNames[0],
|
|
352
|
+
buildVersion: '未完成',
|
|
353
|
+
serverHost: envConfig?.sshHost || '未知',
|
|
354
|
+
branch: originalBranch,
|
|
355
|
+
error: `分支流程失败: ${branchError.message}`
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// 切回原分支
|
|
360
|
+
restoreBranch(originalBranch, hasStash);
|
|
361
|
+
process.exit(1);
|
|
300
362
|
}
|
|
301
363
|
|
|
302
364
|
// 生成构建版本
|
|
@@ -366,19 +428,30 @@ async function deployCommand(config) {
|
|
|
366
428
|
});
|
|
367
429
|
}
|
|
368
430
|
|
|
369
|
-
//
|
|
370
|
-
if (originalBranch) {
|
|
371
|
-
restoreBranch(originalBranch);
|
|
431
|
+
// 出错时切回原分支
|
|
432
|
+
if (needRestore && originalBranch) {
|
|
433
|
+
restoreBranch(originalBranch, hasStash);
|
|
372
434
|
}
|
|
373
435
|
process.exit(1);
|
|
374
436
|
}
|
|
375
437
|
}
|
|
376
438
|
|
|
377
|
-
//
|
|
378
|
-
if (
|
|
379
|
-
|
|
380
|
-
if (
|
|
381
|
-
|
|
439
|
+
// 部署完成后切回原分支
|
|
440
|
+
if (needRestore && originalBranch) {
|
|
441
|
+
// 合并模式:自动切回原分支
|
|
442
|
+
if (autoRestore) {
|
|
443
|
+
console.log('\n📌 自动切回原分支...');
|
|
444
|
+
restoreBranch(originalBranch, false);
|
|
445
|
+
console.log(`✅ 已切回 ${originalBranch},可继续开发`);
|
|
446
|
+
} else {
|
|
447
|
+
// stash 模式:询问是否切回
|
|
448
|
+
const returnAnswer = await prompt('\n是否切回原分支? (y/n): ');
|
|
449
|
+
if (returnAnswer.toLowerCase() === 'y') {
|
|
450
|
+
restoreBranch(originalBranch, hasStash);
|
|
451
|
+
} else if (hasStash) {
|
|
452
|
+
console.log('\n💡 提示: 本地改动已储藏,执行以下命令恢复:');
|
|
453
|
+
console.log(' git stash pop');
|
|
454
|
+
}
|
|
382
455
|
}
|
|
383
456
|
}
|
|
384
457
|
}
|
package/src/git-branch.js
CHANGED
|
@@ -127,6 +127,63 @@ export function pushBranch(branchName) {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* 储藏本地改动(stash)
|
|
132
|
+
* @param {string} branchName - 当前分支名(用于备注)
|
|
133
|
+
* @returns {boolean} 是否成功
|
|
134
|
+
*/
|
|
135
|
+
export function stashChanges(branchName = '') {
|
|
136
|
+
try {
|
|
137
|
+
console.log('\n📦 储藏本地改动...');
|
|
138
|
+
const stashMessage = branchName
|
|
139
|
+
? `stash for test deploy from ${branchName}`
|
|
140
|
+
: 'fe-build-cli-auto-stash';
|
|
141
|
+
execSync(`git stash push -m "${stashMessage}"`, { stdio: 'inherit' });
|
|
142
|
+
console.log('✅ 本地改动已储藏');
|
|
143
|
+
return true;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error('❌ 储藏失败:', error.message);
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 恢复储藏的改动(stash pop)
|
|
152
|
+
* @returns {boolean} 是否成功
|
|
153
|
+
*/
|
|
154
|
+
export function stashPop() {
|
|
155
|
+
try {
|
|
156
|
+
console.log('\n📦 恢复储藏的改动...');
|
|
157
|
+
execSync('git stash pop', { stdio: 'inherit' });
|
|
158
|
+
console.log('✅ 本地改动已恢复');
|
|
159
|
+
return true;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('❌ 恢复失败:', error.message);
|
|
162
|
+
console.log('💡 提示: 可能存在冲突,请手动执行 git stash pop 解决');
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 自动提交当前分支的所有改动
|
|
169
|
+
* @param {string} message - 提交信息
|
|
170
|
+
* @returns {boolean} 是否成功
|
|
171
|
+
*/
|
|
172
|
+
export function autoCommit(message) {
|
|
173
|
+
try {
|
|
174
|
+
console.log('\n📝 自动提交改动...');
|
|
175
|
+
// 添加所有改动
|
|
176
|
+
execSync('git add -A', { stdio: 'inherit' });
|
|
177
|
+
// 提交
|
|
178
|
+
execSync(`git commit -m "${message}"`, { stdio: 'inherit' });
|
|
179
|
+
console.log('✅ 改动已提交');
|
|
180
|
+
return true;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
console.error('❌ 提交失败:', error.message);
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
130
187
|
/**
|
|
131
188
|
* 执行主分支发布流程
|
|
132
189
|
* 流程:当前分支 -> 测试分支 -> 主分支
|
|
@@ -232,16 +289,208 @@ export function executeCurrentBranchFlow() {
|
|
|
232
289
|
};
|
|
233
290
|
}
|
|
234
291
|
|
|
292
|
+
/**
|
|
293
|
+
* 执行 test 环境发布流程(智能模式)
|
|
294
|
+
* @param {object} config - 配置
|
|
295
|
+
* @param {string} config.testBranch - test 分支名
|
|
296
|
+
* @param {boolean} config.mergeChanges - 是否合并本地改动
|
|
297
|
+
* @param {boolean} config.pushToRemote - 是否推送到远程
|
|
298
|
+
* @param {function} config.prompt - 交互提示函数
|
|
299
|
+
* @returns {object} 执行结果
|
|
300
|
+
*/
|
|
301
|
+
export async function executeTestBranchFlow(config) {
|
|
302
|
+
const { testBranch, mergeChanges, pushToRemote = true, prompt } = config;
|
|
303
|
+
const originalBranch = getCurrentBranch();
|
|
304
|
+
const { clean, changes } = checkUncommittedChanges();
|
|
305
|
+
|
|
306
|
+
console.log('\n========================================');
|
|
307
|
+
console.log(' 🌿 Test 环境发布流程');
|
|
308
|
+
console.log('========================================');
|
|
309
|
+
console.log(`当前分支: ${originalBranch}`);
|
|
310
|
+
console.log(`Test 分支: ${testBranch}`);
|
|
311
|
+
console.log(`工作区状态: ${clean ? '干净' : '有未提交改动'}`);
|
|
312
|
+
console.log('========================================');
|
|
313
|
+
|
|
314
|
+
// 情况1:当前分支本身就是 test
|
|
315
|
+
if (originalBranch === testBranch) {
|
|
316
|
+
console.log('\n✓ 当前已在 test 分支');
|
|
317
|
+
pullBranch(testBranch);
|
|
318
|
+
return {
|
|
319
|
+
success: true,
|
|
320
|
+
originalBranch,
|
|
321
|
+
currentBranch: testBranch,
|
|
322
|
+
needRestore: false,
|
|
323
|
+
hasStash: false
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// 情况2:当前分支 ≠ test,无本地改动
|
|
328
|
+
if (clean) {
|
|
329
|
+
console.log('\n✓ 无本地改动,直接切换发布');
|
|
330
|
+
checkoutBranch(testBranch);
|
|
331
|
+
pullBranch(testBranch);
|
|
332
|
+
return {
|
|
333
|
+
success: true,
|
|
334
|
+
originalBranch,
|
|
335
|
+
currentBranch: testBranch,
|
|
336
|
+
needRestore: true,
|
|
337
|
+
hasStash: false,
|
|
338
|
+
autoRestore: true // 无改动模式自动切回
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// 情况3:当前分支 ≠ test,有本地改动
|
|
343
|
+
console.log('\n⚠️ 存在未提交的改动:');
|
|
344
|
+
changes.forEach(change => console.log(` ${change}`));
|
|
345
|
+
|
|
346
|
+
// 如果已确定合并选项,直接执行
|
|
347
|
+
if (mergeChanges === true) {
|
|
348
|
+
return await executeTestMergeFlow(originalBranch, testBranch, pushToRemote);
|
|
349
|
+
} else if (mergeChanges === false) {
|
|
350
|
+
return await executeTestStashFlow(originalBranch, testBranch);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// 否则交互询问
|
|
354
|
+
if (prompt) {
|
|
355
|
+
console.log('\n请选择处理方式:');
|
|
356
|
+
console.log(' 1. 合并改动到 test 发布(提交当前分支,合并到 test)');
|
|
357
|
+
console.log(' 2. 不合并,暂存改动(stash 储藏,用纯净 test 发布)');
|
|
358
|
+
|
|
359
|
+
const answer = await prompt('请输入选项 (1/2): ');
|
|
360
|
+
|
|
361
|
+
if (answer === '1') {
|
|
362
|
+
return await executeTestMergeFlow(originalBranch, testBranch, pushToRemote);
|
|
363
|
+
} else if (answer === '2') {
|
|
364
|
+
return await executeTestStashFlow(originalBranch, testBranch);
|
|
365
|
+
} else {
|
|
366
|
+
throw new Error('无效选项,已取消发布');
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
throw new Error('存在未提交改动,请选择处理方式');
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* 执行合并流程(提交当前分支,合并到 test)
|
|
375
|
+
*/
|
|
376
|
+
async function executeTestMergeFlow(originalBranch, testBranch, pushToRemote) {
|
|
377
|
+
console.log('\n========================================');
|
|
378
|
+
console.log(' 🔀 合并改动发布模式');
|
|
379
|
+
console.log('========================================');
|
|
380
|
+
|
|
381
|
+
try {
|
|
382
|
+
// 1. 自动提交当前分支改动(备注包含原分支名)
|
|
383
|
+
const commitMessage = `auto commit: deploy test from ${originalBranch}`;
|
|
384
|
+
if (!autoCommit(commitMessage)) {
|
|
385
|
+
throw new Error('自动提交失败');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// 2. 推送当前分支到远程
|
|
389
|
+
if (pushToRemote) {
|
|
390
|
+
pushBranch(originalBranch);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// 3. 切换到 test 分支
|
|
394
|
+
checkoutBranch(testBranch);
|
|
395
|
+
pullBranch(testBranch);
|
|
396
|
+
|
|
397
|
+
// 4. 合并当前分支到 test
|
|
398
|
+
if (!mergeBranch(originalBranch, testBranch)) {
|
|
399
|
+
// 合并冲突,切回原分支
|
|
400
|
+
checkoutBranch(originalBranch);
|
|
401
|
+
throw new Error(`合并冲突: ${originalBranch} 到 ${testBranch},请手动解决冲突后重新发布`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// 5. 推送 test 分支
|
|
405
|
+
if (pushToRemote) {
|
|
406
|
+
pushBranch(testBranch);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
console.log('\n========================================');
|
|
410
|
+
console.log('✅ 合并发布流程完成');
|
|
411
|
+
console.log(`当前分支: ${testBranch}`);
|
|
412
|
+
console.log('========================================');
|
|
413
|
+
|
|
414
|
+
return {
|
|
415
|
+
success: true,
|
|
416
|
+
originalBranch,
|
|
417
|
+
currentBranch: testBranch,
|
|
418
|
+
needRestore: true,
|
|
419
|
+
hasStash: false,
|
|
420
|
+
merged: true,
|
|
421
|
+
autoRestore: true // 合并模式自动切回
|
|
422
|
+
};
|
|
423
|
+
} catch (error) {
|
|
424
|
+
// 出错时切回原分支
|
|
425
|
+
try {
|
|
426
|
+
checkoutBranch(originalBranch);
|
|
427
|
+
} catch (e) {
|
|
428
|
+
// 忽略
|
|
429
|
+
}
|
|
430
|
+
throw error;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* 执行暂存流程(stash 储藏,用纯净 test 发布)
|
|
436
|
+
*/
|
|
437
|
+
async function executeTestStashFlow(originalBranch, testBranch) {
|
|
438
|
+
console.log('\n========================================');
|
|
439
|
+
console.log(' 📦 暂存改动发布模式');
|
|
440
|
+
console.log('========================================');
|
|
441
|
+
|
|
442
|
+
try {
|
|
443
|
+
// 1. 储藏本地改动(备注包含原分支名)
|
|
444
|
+
if (!stashChanges(originalBranch)) {
|
|
445
|
+
throw new Error('储藏改动失败');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// 2. 切换到 test 分支
|
|
449
|
+
checkoutBranch(testBranch);
|
|
450
|
+
pullBranch(testBranch);
|
|
451
|
+
|
|
452
|
+
console.log('\n========================================');
|
|
453
|
+
console.log('✅ 暂存发布流程完成');
|
|
454
|
+
console.log(`当前分支: ${testBranch}`);
|
|
455
|
+
console.log('========================================');
|
|
456
|
+
|
|
457
|
+
return {
|
|
458
|
+
success: true,
|
|
459
|
+
originalBranch,
|
|
460
|
+
currentBranch: testBranch,
|
|
461
|
+
needRestore: true,
|
|
462
|
+
hasStash: true,
|
|
463
|
+
autoRestore: false // stash 模式询问是否切回
|
|
464
|
+
};
|
|
465
|
+
} catch (error) {
|
|
466
|
+
// 出错时切回原分支并恢复 stash
|
|
467
|
+
try {
|
|
468
|
+
checkoutBranch(originalBranch);
|
|
469
|
+
stashPop();
|
|
470
|
+
} catch (e) {
|
|
471
|
+
// 忽略
|
|
472
|
+
}
|
|
473
|
+
throw error;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
235
477
|
/**
|
|
236
478
|
* 发布后切回原分支
|
|
237
479
|
* @param {string} originalBranch - 原分支名
|
|
480
|
+
* @param {boolean} hasStash - 是否有储藏的改动
|
|
238
481
|
*/
|
|
239
|
-
export function restoreBranch(originalBranch) {
|
|
482
|
+
export function restoreBranch(originalBranch, hasStash = false) {
|
|
240
483
|
const currentBranch = getCurrentBranch();
|
|
241
484
|
if (currentBranch !== originalBranch) {
|
|
242
485
|
console.log(`\n📌 切回原分支: ${originalBranch}`);
|
|
243
486
|
checkoutBranch(originalBranch);
|
|
244
487
|
}
|
|
488
|
+
|
|
489
|
+
// 如果有储藏的改动,提示恢复
|
|
490
|
+
if (hasStash) {
|
|
491
|
+
console.log('\n💡 提示: 本地改动已储藏,执行以下命令恢复:');
|
|
492
|
+
console.log(' git stash pop');
|
|
493
|
+
}
|
|
245
494
|
}
|
|
246
495
|
|
|
247
496
|
export default {
|
|
@@ -253,7 +502,11 @@ export default {
|
|
|
253
502
|
pullBranch,
|
|
254
503
|
mergeBranch,
|
|
255
504
|
pushBranch,
|
|
505
|
+
stashChanges,
|
|
506
|
+
stashPop,
|
|
507
|
+
autoCommit,
|
|
256
508
|
executeMainBranchFlow,
|
|
257
509
|
executeCurrentBranchFlow,
|
|
510
|
+
executeTestBranchFlow,
|
|
258
511
|
restoreBranch
|
|
259
512
|
};
|
package/src/index.js
CHANGED