Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 10, 2025

When creating a PR from a single commit, the extension now unwraps commit message body lines that were wrapped at 72 characters, matching GitHub's native behavior.

Changes

  • Added unwrapCommitMessageBody function: Joins consecutive non-formatted lines while preserving:

    • Blank lines (paragraph breaks)
    • List items (-, *, +, numbered)
    • Blockquotes (>)
    • Indented code blocks
  • Updated titleAndBodyFrom: Applies unwrapping to commit message bodies before setting PR description

  • Test coverage: Added 9 test cases for wrapped paragraphs, lists, quotes, indented blocks, and mixed content

Example

Before:

This is a long commit message that has been wrapped at 72
characters to fit conventional Git formatting standards.

After:

This is a long commit message that has been wrapped at 72 characters to fit conventional Git formatting standards.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • update.code.visualstudio.com
    • Triggering command: /opt/hostedtoolcache/node/20.19.6/x64/bin/node node ./out/src/test/runTests.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Join commit message lines on PR creation</issue_title>
<issue_description>Both on GitHub and this extension, there's functionality where if you're creating a PR from a single commit, it will use the commit subject as the PR title and the commit message body as the PR description. In Git commits, it's conventional to wrap commit messages at 72 characters (VS Code even has a default ruler for this) for command-line tooling.

In GitHub, there's some smartness to unwrap those lines when translating the commit message body into the PR description. It would be nice if this extension had that functionality as well.</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI self-assigned this Dec 10, 2025
Copilot AI and others added 4 commits December 10, 2025 09:51
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
- Add unwrapCommitMessageBody function to join wrapped lines
- Preserve blank lines, list items, quotes, and indented content
- Add comprehensive tests for various unwrapping scenarios
- Matches GitHub's behavior when converting commit messages to PR descriptions

Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
- Extract regex pattern to named constant PRESERVE_LINE_PATTERN
- Replace deprecated substr() with slice()
- Improve regex to match only spaces/tabs explicitly instead of \s
- Add detailed comments explaining the pattern

Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
- Place hyphen at end of character class for clarity
- Extract hasBody condition to avoid duplication

Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
Copilot AI changed the title [WIP] Add functionality to unwrap commit message lines on PR creation Unwrap 72-character wrapped commit message lines when creating PRs Dec 10, 2025
Copilot AI requested a review from alexr00 December 10, 2025 10:04
Copy link

@justingrant justingrant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see this PR, but I see a few problems.

Comment on lines +2890 to +2950
if (!body) {
return body;
}

// Pattern to detect lines that should be preserved (not joined):
// - Lines starting with whitespace (indented/code blocks)
// - Lines starting with list markers (*, -, +, >)
// - Lines starting with numbered list items (e.g., "1. ")
const PRESERVE_LINE_PATTERN = /^[ \t*+>\-]|^\d+\./;

const lines = body.split('\n');
const result: string[] = [];
let i = 0;

while (i < lines.length) {
const line = lines[i];

// Preserve blank lines
if (line.trim() === '') {
result.push(line);
i++;
continue;
}

// Check if this line should NOT be joined with the next
// Lines that start with special formatting characters should be preserved
const shouldPreserveLine = PRESERVE_LINE_PATTERN.test(line);

if (shouldPreserveLine) {
result.push(line);
i++;
continue;
}

// Start accumulating lines that should be joined
let joinedLine = line;
i++;

// Keep joining lines until we hit a blank line or a line that shouldn't be joined
while (i < lines.length) {
const nextLine = lines[i];

// Stop at blank lines
if (nextLine.trim() === '') {
break;
}

// Stop at lines that start with special formatting
if (PRESERVE_LINE_PATTERN.test(nextLine)) {
break;
}

// Join this line with a space
joinedLine += ' ' + nextLine;
i++;
}

result.push(joinedLine);
}

return result.join('\n');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few problems with your code:

  • Having two nested loops is unnecessarily complicated.
  • You don't support code blocks that are fenced with ```
  • Detection of indented code is flawed because it doesn't account for nested list items or list item continuations that have 4+ spaces at the start of the line.

Here's a revised version:

Suggested change
if (!body) {
return body;
}
// Pattern to detect lines that should be preserved (not joined):
// - Lines starting with whitespace (indented/code blocks)
// - Lines starting with list markers (*, -, +, >)
// - Lines starting with numbered list items (e.g., "1. ")
const PRESERVE_LINE_PATTERN = /^[ \t*+>\-]|^\d+\./;
const lines = body.split('\n');
const result: string[] = [];
let i = 0;
while (i < lines.length) {
const line = lines[i];
// Preserve blank lines
if (line.trim() === '') {
result.push(line);
i++;
continue;
}
// Check if this line should NOT be joined with the next
// Lines that start with special formatting characters should be preserved
const shouldPreserveLine = PRESERVE_LINE_PATTERN.test(line);
if (shouldPreserveLine) {
result.push(line);
i++;
continue;
}
// Start accumulating lines that should be joined
let joinedLine = line;
i++;
// Keep joining lines until we hit a blank line or a line that shouldn't be joined
while (i < lines.length) {
const nextLine = lines[i];
// Stop at blank lines
if (nextLine.trim() === '') {
break;
}
// Stop at lines that start with special formatting
if (PRESERVE_LINE_PATTERN.test(nextLine)) {
break;
}
// Join this line with a space
joinedLine += ' ' + nextLine;
i++;
}
result.push(joinedLine);
}
return result.join('\n');
const rawLines = body.split(/\r?\n/);
const result: string[] = [];
let inFencedCodeBlock = false;
let prevWasCode = false;
for (const rawLine of rawLines) {
const line = rawLine.trimEnd(); // Remove trailing space
const trimmed = line.trim();
const prev = result[result.length - 1];
const isList = (s: string) => /^\s*[>\*\-\+]\s/.test(s);
const indentSpaces = line.match(/^( *)/)?.[1].length ?? 0;
const isListItemContinuation: boolean =
!prevWasCode && isList(prev) && indentSpaces >= 2;
const isIndentedCode: boolean =
!isListItemContinuation && (indentSpaces >= 4 || line.startsWith('\t'));
const isCode: boolean = inFencedCodeBlock || isIndentedCode;
if (line.startsWith('```')) {
// Start or end of fenced code block is never joined
inFencedCodeBlock = !inFencedCodeBlock;
result.push(line);
} else if (!line || isCode || isList(line) || !prev || !result.length) {
// Empty/code/list lines never join with the previous line.
// Also don't join the first line, or if previous line is blank.
result.push(line);
} else {
// Otherwise, join with previous line
result[result.length - 1] = prev + ' ' + trimmed;
}
prevWasCode = isCode;
}
return result.join('\n');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Join commit message lines on PR creation

3 participants