test(commit-split): 改名時別漏掉舊檔的刪除,失敗時說出做到哪裡
git diff --name-only 預設偵測改名,只印出目的地那一個路徑。來源的刪除因此被漏掉—— 留在 index 裡沒被提交,而腳本還回報成功,要等下一次跑才會發現工作區不乾淨。加 --no-renames。 某一批提交失敗時,錯誤現在會列出前面已經建立的那幾顆 commit。不回捲它們:那會動到使用者的 歷史,而那幾顆本身是好的;但一定要說出做到哪裡,否則重跑前得自己去翻 git log。 類型對照表補上目標專案常見的測試擺法:tests/、spec/、__tests__/,以及放在被測檔案旁邊的 user.test.js。先前只認 test/,目標專案的測試會被併進 feat 那一批。
This commit is contained in:
@@ -42,6 +42,11 @@ const subjects = (repo) =>
|
||||
const CLASSIFY = [
|
||||
{ path: 'test/claim.test.js', type: 'test', why: '測試檔' },
|
||||
{ path: 'test/helpers/stub-gitea.js', type: 'test', why: '測試用的 helper 也算測試' },
|
||||
{ path: 'tests/user_test.py', type: 'test', why: '目標專案未必叫 test/' },
|
||||
{ path: 'spec/user_spec.rb', type: 'test', why: '同上' },
|
||||
{ path: '__tests__/user.js', type: 'test', why: '同上' },
|
||||
{ path: 'src/user.test.js', type: 'test', why: '測試與程式碼放在一起也很常見' },
|
||||
{ path: 'src/User.spec.ts', type: 'test', why: '同上' },
|
||||
{ path: 'README.md', type: 'docs', why: '根目錄的說明文件' },
|
||||
{ path: 'AGENTS.md', type: 'docs', why: '同上' },
|
||||
{ path: 'package.json', type: 'chore', why: '專案設定' },
|
||||
@@ -306,6 +311,41 @@ test('被刪掉的檔案也照樣分類、照樣進 commit', async (t) => {
|
||||
assert.equal(repo.git('status', '--porcelain'), '');
|
||||
});
|
||||
|
||||
test('改名時舊檔的刪除也要進 commit,不能只提交新檔', async (t) => {
|
||||
// git diff --name-only 預設偵測改名,只印目的地那一個路徑。漏掉來源等於把刪除留在
|
||||
// index 裡,而腳本還回報成功——下一次跑才會發現工作區不乾淨。
|
||||
const repo = withRepo(t);
|
||||
write(repo, 'scripts/old.js');
|
||||
repo.git('add', '-A');
|
||||
repo.git('commit', '-qm', '先有這個檔案');
|
||||
repo.git('mv', 'scripts/old.js', 'scripts/new.js');
|
||||
|
||||
const { code, json } = await run(repo, ['--type', 'refactor', '--scope', '改名', '--subject', '換個名字']);
|
||||
|
||||
assert.equal(code, 0, JSON.stringify(json));
|
||||
assert.deepEqual(json.data.commits[0].files, ['scripts/new.js', 'scripts/old.js']);
|
||||
assert.equal(repo.git('status', '--porcelain'), '', '改名的兩邊都要進同一顆 commit');
|
||||
});
|
||||
|
||||
// ── 中途失敗 ───────────────────────────────────────────────────────
|
||||
|
||||
test('某一批提交失敗時,錯誤要說出前面已經建立了哪幾顆 commit', async (t) => {
|
||||
// 沒說的話,使用者不知道做到哪裡,重跑前得自己去翻 git log
|
||||
const repo = withRepo(t);
|
||||
write(repo, 'scripts/one.js', 'test/one.test.js');
|
||||
// 用 pre-commit hook 擋掉測試那一批
|
||||
const hook = join(repo.dir, '.git', 'hooks', 'pre-commit');
|
||||
mkdirSync(dirname(hook), { recursive: true });
|
||||
writeFileSync(hook, '#!/bin/sh\ngit diff --cached --name-only | grep -q "^test/" && exit 1\nexit 0\n', { mode: 0o755 });
|
||||
|
||||
const { code, json } = await run(repo, ['--type', 'feat', '--subject', '做一件事']);
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'COMMIT_FAILED');
|
||||
assert.match(json.error.message, /feat\(one\): 做一件事/, '要指名已經建立的那一顆');
|
||||
assert.match(json.error.message, /test\(one\)/, '也要指名是哪一批失敗的');
|
||||
});
|
||||
|
||||
// ── --dry-run ─────────────────────────────────────────────────────
|
||||
|
||||
test('--dry-run 印出將建立的 commit 與各自的檔案,但不提交', async (t) => {
|
||||
|
||||
Reference in New Issue
Block a user