fix(git-rewrite): preserve messages when squashing commits
swadhinbiswas committed 8 months ago
0fdca41
1 parent 0d21323
commit 0fdca41
1 file changed
+15 -15
Showing 1 changed file+15-15
▼src/lib/git-rewrite.ts
+15-15
| @@ -1,7 +1,6 @@ | ||
1 | 1 | |
2 | 2 | import { simpleGit, SimpleGit } from "simple-git"; |
3 | 3 | import { acquireRepo, releaseRepo } from "./git-storage"; |
4 | -import { logger } from "./logger"; | |
5 | 4 | |
6 | 5 | export type RewriteOperation = |
7 | 6 | | { type: "pick"; hash: string } |
| @@ -36,8 +35,6 @@ export async function rewriteBranchHistory( | ||
36 | 35 | |
37 | 36 | // Example: [pick A, squash B, pick C] -> Result: A+B, C. |
38 | 37 | |
39 | - let previousCommitWasSquash = false; | |
40 | - | |
41 | 38 | for (let i = 0; i < operations.length; i++) { |
42 | 39 | const op = operations[i]; |
43 | 40 | |
| @@ -47,33 +44,26 @@ export async function rewriteBranchHistory( | ||
47 | 44 | if (op.type === "pick") { |
48 | 45 | // git cherry-pick <hash> |
49 | 46 | await git.raw(["cherry-pick", op.hash]); |
50 | - previousCommitWasSquash = false; | |
51 | 47 | } |
52 | 48 | else if (op.type === "reword") { |
53 | 49 | await git.raw(["cherry-pick", op.hash]); |
54 | 50 | await git.commit(op.newMessage, { "--amend": null }); |
55 | - previousCommitWasSquash = false; | |
56 | 51 | } |
57 | 52 | else if (op.type === "squash") { |
58 | 53 | // Squash: cherry-pick -n, then commit --amend (to previous) |
59 | 54 | // If first commit is squash, it fails (cannot squash into nothing). |
60 | 55 | // We assume valid input from UI. |
61 | 56 | |
57 | + const previousMessage = await readCommitMessage(git, "HEAD"); | |
58 | + const squashMessage = await readCommitMessage(git, op.hash); | |
59 | + | |
62 | 60 | // 1. Apply changes without commit |
63 | 61 | // cherry-pick -n <hash> |
64 | 62 | await git.raw(["cherry-pick", "-n", op.hash]); |
65 | 63 | |
66 | 64 | // 2. Amend previous commit |
67 | - // This reuses previous message + new message? | |
68 | - // simple 'git commit --amend --no-edit' keeps old message. | |
69 | - // Let's just append for now or keep old. | |
70 | - // Ideally we concatenate messages. | |
71 | - | |
72 | - // Only getting subject here, bodies are harder without parsing. | |
73 | - // MVP: Keep previous message (fixup behavior) or just generic amend | |
74 | - await git.commit("", { "--amend": null, "--no-edit": null }); | |
75 | - | |
76 | - previousCommitWasSquash = true; | |
65 | + const combinedMessage = combineCommitMessages(previousMessage, squashMessage); | |
66 | + await git.commit(combinedMessage, { "--amend": null }); | |
77 | 67 | } |
78 | 68 | } catch (e: any) { |
79 | 69 | if (e.message.includes("conflict")) { |
| @@ -96,3 +86,13 @@ export async function rewriteBranchHistory( | ||
96 | 86 | await releaseRepo(repoOwner, repoName, true); // True because we pushed |
97 | 87 | } |
98 | 88 | } |
89 | + | |
90 | +async function readCommitMessage(git: SimpleGit, rev: string): Promise<string> { | |
91 | + return (await git.raw(["show", "-s", "--format=%B", rev])).trim(); | |
92 | +} | |
93 | + | |
94 | +function combineCommitMessages(previousMessage: string, squashMessage: string): string { | |
95 | + if (!previousMessage) return squashMessage || "squashed commit"; | |
96 | + if (!squashMessage || previousMessage === squashMessage) return previousMessage; | |
97 | + return `${previousMessage}\n\n${squashMessage}`.trim(); | |
98 | +} | |
99 | 99 | |