Skip to content

feat(worktree): use human-readable names for worktree branches#2340

Open
MukundaKatta wants to merge 1 commit into
PostHog:mainfrom
MukundaKatta:fix/human-readable-worktree-branches
Open

feat(worktree): use human-readable names for worktree branches#2340
MukundaKatta wants to merge 1 commit into
PostHog:mainfrom
MukundaKatta:fix/human-readable-worktree-branches

Conversation

@MukundaKatta
Copy link
Copy Markdown

Problem

Closes #1844

New worktrees were labeled with random 4-digit numbers (crypto.randomInt(1000, 10000)), which read like short SHA snippets and made it momentarily unclear which worktree you were on.

Changes

  • Added packages/git/src/worktree-name.ts with a small curated adjective-noun word list and a generateHumanReadableName() helper that returns names like swift-otter-42.
  • WorktreeManager.generateWorktreeName() now delegates to this helper. All existing collision-handling paths and the ${name}${Date.now()} defensive fallback are unchanged.
  • Names stay lowercase, filesystem-safe (a-z, 0-9, -), and short (under 32 chars).
  • The ~116k combinations from 36 adjectives x 36 nouns x 90 suffix values keep collisions rare in practice.

How did you test this?

  • Added packages/git/src/worktree-name.test.ts covering the name shape, character safety, length bound, and rough uniqueness over 50 draws.
  • pnpm --filter @posthog/git test -> 159 passed (8 files), including the 4 new ones.
  • pnpm --filter @posthog/git typecheck -> clean.
  • biome check on the touched files -> clean.

Publish to changelog?

no

Worktrees were named with random 4-digit numbers that read like SHA
snippets, making it momentarily unclear which worktree you were on.
Generate adjective-noun-NN names instead (e.g. "swift-otter-42") from
a small curated word list. Names stay filesystem-safe and short.

Fixes PostHog#1844
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 24, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/git/src/worktree-name.test.ts:10-31
The team's standard is to prefer parameterised tests over manual loops. The three loop-based cases ("varies", "filesystem-safe", "compact") can each be expressed as `it.each` calls, making each individual sample a named test case and avoiding an imperative loop that obscures the intent.

```suggestion
  it("produces varied names over multiple calls", () => {
    const names = new Set(Array.from({ length: 50 }, generateHumanReadableName));
    // With 36 * 36 * 90 = ~116k combinations, 50 draws should yield
    // many unique values. Allow generous slack for randomness.
    expect(names.size).toBeGreaterThan(20);
  });

  it.each(Array.from({ length: 25 }, generateHumanReadableName))(
    "uses only filesystem-safe characters: %s",
    (name) => {
      expect(name).toMatch(/^[a-z0-9-]+$/);
    },
  );

  it.each(Array.from({ length: 25 }, generateHumanReadableName))(
    "stays compact (under 32 chars): %s",
    (name) => {
      expect(name.length).toBeLessThanOrEqual(32);
    },
  );
```

Reviews (1): Last reviewed commit: "feat(worktree): use human-readable names..." | Re-trigger Greptile

Comment on lines +10 to +31
it("produces varied names over multiple calls", () => {
const names = new Set<string>();
for (let i = 0; i < 50; i++) {
names.add(generateHumanReadableName());
}
// With 36 * 36 * 90 = ~116k combinations, 50 draws should yield
// many unique values. Allow generous slack for randomness.
expect(names.size).toBeGreaterThan(20);
});

it("uses only filesystem-safe characters", () => {
for (let i = 0; i < 25; i++) {
const name = generateHumanReadableName();
expect(name).toMatch(/^[a-z0-9-]+$/);
}
});

it("stays compact (under 32 chars)", () => {
for (let i = 0; i < 25; i++) {
expect(generateHumanReadableName().length).toBeLessThanOrEqual(32);
}
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 The team's standard is to prefer parameterised tests over manual loops. The three loop-based cases ("varies", "filesystem-safe", "compact") can each be expressed as it.each calls, making each individual sample a named test case and avoiding an imperative loop that obscures the intent.

Suggested change
it("produces varied names over multiple calls", () => {
const names = new Set<string>();
for (let i = 0; i < 50; i++) {
names.add(generateHumanReadableName());
}
// With 36 * 36 * 90 = ~116k combinations, 50 draws should yield
// many unique values. Allow generous slack for randomness.
expect(names.size).toBeGreaterThan(20);
});
it("uses only filesystem-safe characters", () => {
for (let i = 0; i < 25; i++) {
const name = generateHumanReadableName();
expect(name).toMatch(/^[a-z0-9-]+$/);
}
});
it("stays compact (under 32 chars)", () => {
for (let i = 0; i < 25; i++) {
expect(generateHumanReadableName().length).toBeLessThanOrEqual(32);
}
});
it("produces varied names over multiple calls", () => {
const names = new Set(Array.from({ length: 50 }, generateHumanReadableName));
// With 36 * 36 * 90 = ~116k combinations, 50 draws should yield
// many unique values. Allow generous slack for randomness.
expect(names.size).toBeGreaterThan(20);
});
it.each(Array.from({ length: 25 }, generateHumanReadableName))(
"uses only filesystem-safe characters: %s",
(name) => {
expect(name).toMatch(/^[a-z0-9-]+$/);
},
);
it.each(Array.from({ length: 25 }, generateHumanReadableName))(
"stays compact (under 32 chars): %s",
(name) => {
expect(name.length).toBeLessThanOrEqual(32);
},
);

Context Used: Do not attempt to comment on incorrect alphabetica... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/git/src/worktree-name.test.ts
Line: 10-31

Comment:
The team's standard is to prefer parameterised tests over manual loops. The three loop-based cases ("varies", "filesystem-safe", "compact") can each be expressed as `it.each` calls, making each individual sample a named test case and avoiding an imperative loop that obscures the intent.

```suggestion
  it("produces varied names over multiple calls", () => {
    const names = new Set(Array.from({ length: 50 }, generateHumanReadableName));
    // With 36 * 36 * 90 = ~116k combinations, 50 draws should yield
    // many unique values. Allow generous slack for randomness.
    expect(names.size).toBeGreaterThan(20);
  });

  it.each(Array.from({ length: 25 }, generateHumanReadableName))(
    "uses only filesystem-safe characters: %s",
    (name) => {
      expect(name).toMatch(/^[a-z0-9-]+$/);
    },
  );

  it.each(Array.from({ length: 25 }, generateHumanReadableName))(
    "stays compact (under 32 chars): %s",
    (name) => {
      expect(name.length).toBeLessThanOrEqual(32);
    },
  );
```

**Context Used:** Do not attempt to comment on incorrect alphabetica... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

Use human-readable names for worktree branches instead of random hashes

1 participant