Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
097c743
fix: five bugs the new tests found
antonarnaudov Sep 29, 2026
102b4d1
test: cover the least-tested code, from the git layer to the desktop …
antonarnaudov Sep 29, 2026
6c1d271
ci: measure coverage per workspace and merge by line
antonarnaudov Sep 29, 2026
8eb8ca8
test(extension): the todo check reads newer git's "pick <sha> # subje…
antonarnaudov Sep 29, 2026
2ae9c60
fix(git): five git-layer bugs the new tests found
antonarnaudov Sep 29, 2026
3e166dd
fix(merge): two conflict-file bugs in the merge editor's writer
antonarnaudov Sep 29, 2026
b474f86
fix: app-level bugs the new tests found
antonarnaudov Sep 29, 2026
91487c9
release: extension 1.17.0, desktop 2.4.0, Merge Studio 1.2.0
antonarnaudov Sep 29, 2026
888ecd1
Merge remote-tracking branch 'origin/fix/bugs-from-coverage' into rel…
antonarnaudov Sep 29, 2026
392e8e9
release: the fixes found by the new tests, in the changelogs and rele…
antonarnaudov Sep 29, 2026
b153245
test: wait on conditions, not turn counts, in two tests a busy runner…
antonarnaudov Sep 29, 2026
152789e
Merge remote-tracking branch 'origin/fix/bugs-from-coverage' into rel…
antonarnaudov Sep 29, 2026
a8148da
fix(desktop): closing the window kills a clone's whole process tree o…
antonarnaudov Sep 29, 2026
ba9358b
fix(git): five git-layer bugs the new tests found
antonarnaudov Sep 29, 2026
8ae8734
fix(merge): two conflict-file bugs in the merge editor's writer
antonarnaudov Sep 29, 2026
aca3ff7
fix: app-level bugs the new tests found
antonarnaudov Sep 29, 2026
aeecb42
test: wait on conditions, not turn counts, in two tests a busy runner…
antonarnaudov Sep 29, 2026
54f2ed6
Merge remote-tracking branch 'origin/fix/bugs-from-coverage' into rel…
antonarnaudov Sep 29, 2026
74a4dfb
test(desktop): the fake GitHub API matches by origin, not by prefix
antonarnaudov Sep 29, 2026
b2b03e4
fix(git): five git-layer bugs the new tests found
antonarnaudov Sep 29, 2026
e88b4a0
fix(merge): two conflict-file bugs in the merge editor's writer
antonarnaudov Sep 29, 2026
fe8826d
fix: app-level bugs the new tests found
antonarnaudov Sep 29, 2026
044927e
test: wait on conditions, not turn counts, in two tests a busy runner…
antonarnaudov Sep 29, 2026
c8c1f79
Merge remote-tracking branch 'origin/fix/bugs-from-coverage' into rel…
antonarnaudov Sep 29, 2026
74d9f1f
test(desktop): escape every regex metacharacter in a pinned version, …
antonarnaudov Sep 29, 2026
96876c7
chore: the AI features are just AI — remove every trace of an old pro…
antonarnaudov Sep 29, 2026
1ade24a
feat(desktop): a Dark style setting — Graphite or Neon, for the windo…
antonarnaudov Sep 29, 2026
407f79f
test(desktop): escape every regex metacharacter in a CSS selector, no…
antonarnaudov Sep 29, 2026
408508a
test: Windows-safe cleanup, paths and waits in the new tests
antonarnaudov Sep 29, 2026
d6b0cb2
test: compare the graph host's working-tree path separator-agnostically
antonarnaudov Sep 29, 2026
d659522
Merge remote-tracking branch 'origin/fix/bugs-from-coverage' into rel…
antonarnaudov Sep 30, 2026
274ef57
test: strip the Dock icon's folder on either separator
antonarnaudov Sep 30, 2026
99dd4c4
Merge remote-tracking branch 'origin/main' into release/ext-1.17-app-…
antonarnaudov Sep 30, 2026
115407a
test: drop main's copy of the AI core tests, already renamed here
antonarnaudov Sep 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ You're picking up GitStudio. This doc is the context you need so you don't relit
1. **One flagship extension, not a swarm.** GitStudio is `gitstudio.gitstudio` — a single extension that grows pillar by pillar (the GitLens model). Merge Studio stays a separate, focused product. They **share an engine, not a listing**.
2. **Publisher = brand, extension = product.** The publisher id `gitstudio` is the umbrella; products are extensions under it. (This distinction cost us a day of confusion — see the war-story; don't repeat it.)
3. **Reuse before rebuild.** The merge engine and webview ribbon stack are proven. Extract, don't fork-and-drift.
4. **AI (GitBrain) is optional + BYO-key.** Don't make the core depend on it.
4. **AI is optional + BYO-key.** Don't make the core depend on it.

## Suggested first moves (highest leverage first)

1. **Extract the shared engine.** Pull `merge-studio/src/engine/` (and the parts of `webview/` that render ribbons/decorations) into a `@gitstudio/engine` package this repo can consume. Keep Merge Studio building against it too. This is the foundation — do it first and do it cleanly.
2. **Scaffold the extension** from `../vscode-extension-starter` (esbuild bundling, `vscode:prepublish`, `.vscodeignore`, CI + release workflows). You get a publishable shell in minutes.
3. **Ship pillar #1: Blame & history.** It's the highest-value, lowest-risk feature after merge — ambient (decorations + hovers, no custom editor needed), and it makes the extension immediately useful. Resist starting with the commit graph (high effort, easy to get visually wrong).
4. **Then the commit graph / log**, reusing the webview muscle.
5. **GitBrain last**, once there's a surface to attach it to (commit-message gen on the staging view, "explain this diff" on the diff/history view).
5. **AI features last**, once there's a surface to attach it to (commit-message gen on the staging view, "explain this diff" on the diff/history view).

## How to work with the codebases

Expand Down Expand Up @@ -50,7 +50,7 @@ Don't hand-publish. Use the pipeline:

- License for GitStudio (Merge Studio is MIT — match it, or go source-available?).
- Monorepo (merge-studio + gitstudio + shared engine) vs. separate repos with a published `@gitstudio/engine`?
- Free vs. freemium for the suite (GitBrain/AI is the natural paid tier).
- Free vs. freemium for the suite (AI is the natural paid tier).
- How much of Merge Studio folds *into* GitStudio vs. stays standalone long-term.

Start with the engine extraction and blame pillar. Everything else builds on those.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Everything ships in one extension (`gitstudio.gitstudio`) and one desktop app, b
| **Rewrite** | Drag-to-reorder interactive rebase (pick · reword · edit · squash · fixup · drop); a universal, reflog-powered **Undo** safety net (never hijacks `Ctrl/Cmd+Z`). |
| **Manage** | Branches (live ↑/↓ badges, fetch-in-place, pull without checkout), remotes, tags, first-class stashes, worktrees; GitHub-style branch compare; status-bar sync with in-view Push/Pull. |
| **Collaborate** | In-editor GitHub pull-request review — list, check out, diff, comment inline, submit, merge, create. |
| **Assist** | GitBrain — optional, bring-your-own-key (Anthropic or any OpenAI-compatible endpoint, including local Ollama / LM Studio) or zero-key (Copilot): AI commit messages, explain-diff, summaries. With Copilot it works with nothing to set up, otherwise it is off until you connect a provider; keys live in SecretStorage; AI never gates a Git operation. |
| **Assist** | AI features — optional, bring-your-own-key (Anthropic or any OpenAI-compatible endpoint, including local Ollama / LM Studio) or zero-key (Copilot): AI commit messages, explain-diff, summaries. With Copilot it works with nothing to set up, otherwise it is off until you connect a provider; keys stay on your machine in GitStudio's own encrypted store; AI never gates a Git operation. |

## The desktop app

Expand Down Expand Up @@ -203,7 +203,7 @@ Issues and pull requests are welcome at [GitStudioHQ/gitstudio](https://github.c
npm test && npm run check-types && npm run check-purity
```

[CONTRIBUTING.md](CONTRIBUTING.md) has the rest, and [`docs/merge-studio.md`](docs/merge-studio.md) explains how the merge code is shared with Merge Studio and how a pull request opened on its repository comes back here.
[CONTRIBUTING.md](CONTRIBUTING.md) has the rest (and the [code of conduct](CODE_OF_CONDUCT.md); report security problems privately, as [SECURITY.md](SECURITY.md) says), and [`docs/merge-studio.md`](docs/merge-studio.md) explains how the merge code is shared with Merge Studio and how a pull request opened on its repository comes back here.

## Facts

Expand All @@ -213,6 +213,8 @@ npm test && npm run check-types && npm run check-purity
| **Desktop** | [GitHub Releases](https://github.com/GitStudioHQ/gitstudio/releases) — `.dmg` (arm64 + x64), `.exe`, `.AppImage`, `.deb`, `.rpm`, `.tar.gz` |
| **Website** | [gitstudio.dev](https://gitstudio.dev) |
| **License** | **Apache-2.0** |
| **Privacy** | What each product sends, and how to turn it off: [desktop](apps/desktop/PRIVACY.md) · [extension](apps/extension/PRIVACY.md) · [Merge Studio](apps/merge-studio/PRIVACY.md) |
| **Security** | [SECURITY.md](SECURITY.md) — report privately, through the repository's Security tab |
| **Sibling product** | [Merge Studio](https://marketplace.visualstudio.com/items?itemName=gitstudio.merge-studio) — `gitstudio.merge-studio`, the merge-only extension. Built from `apps/merge-studio` and the shared packages here, exported to [GitStudioHQ/merge-studio](https://github.com/GitStudioHQ/merge-studio). Shares its merge editor, not a listing. |

## Architecture notes
Expand Down
32 changes: 31 additions & 1 deletion apps/desktop/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ The VS Code / Cursor extension has its own changelog at
separately — desktop releases are tagged `app-v*`, extension releases `ext-v*` —
but they share the same engine, so most Git behaviour lands in both at once.

## [Unreleased]
## [2.4.0] - 2026-09-29

### Added
- **Dark style: Graphite or Neon.** Settings ▸ Appearance has a new *Dark
style* choice, shown as each style's Dock icon beside a swatch of its
window, and it sets both at once. **Graphite** (the default) is the grey
icon macOS shows while GitStudio is closed, with the familiar dark theme, so
opening the app no longer changes the Dock icon. **Neon** is the
near-black icon with a deeper, more violet dark theme; its Dock icon applies
while GitStudio runs, and macOS still shows the Graphite icon while it is
closed. The launch screen opens in the chosen style from its first frame.
- **A launch screen.** GitStudio's window now opens straight onto the
whole GitStudio mark — the app icon's cube, its commit graph and the name,
settling gently into place — instead of appearing late and painting itself
Expand Down Expand Up @@ -71,6 +79,28 @@ but they share the same engine, so most Git behaviour lands in both at once.
Dock doesn't get your shell's PATH, and a Windows app keeps the PATH it
started with.

- **Push no longer re-creates a branch someone deleted on the remote.** When a
branch's remote copy was deleted but it still tracked it, Push published it
again. It now stops and says the branch it tracks is gone.
- **A repository with no commits yet shows "No commits yet"** in the graph,
not "Couldn't load history".
- **A failed clone says why.** The clone sheet showed git's last line — often
a fragment like "and the repository exists." — instead of the reason.
- **On Windows, repositories are grouped inside the folders they sit in.**
The folders you track came from the folder picker with backslashes, and
every repository landed outside them.
- **Release tags show their date.** Annotated tags — most releases — came
back with no date.
- **A reword keeps its `#` lines after the rebase pauses**, a rebase git
refuses up front is no longer shown as stopped on conflicts, and Stash &
Retry is not offered for a branch or commit git doesn't know.
- **Merge editor: a conflict is written where it happened**, and an add/add
conflict no longer carries an extra blank line on each side.
- **The Assistant:** cancelling a chat just as its message was sent could
crash the app's main process; an Azure OpenAI address ending in `/` before
its `?api-version=` produced a broken URL; and the first connection added on
a fresh install could leak into later ones.

### Security
- **Crash reports no longer carry a commit's subject, or a branch name git
prints without quotes.** When a rebase, cherry-pick, revert or `git am`
Expand Down
16 changes: 12 additions & 4 deletions apps/desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@ when their secrets are absent.

## Privacy

No accounts, no usage tracking. During the beta the app sends **anonymous,
scrubbed crash reports** (on by default; toggle via **Help → Send Anonymous
Crash Reports**) to the same collector as the extension. Details in
[PRIVACY.md](PRIVACY.md).
No accounts, no usage tracking. What the app does send:

- **anonymous, scrubbed crash reports**, on by default (**Help → Send
Anonymous Crash Reports** turns them off), to the same collector as the
extension;
- **update checks** to GitHub Releases, which ask before downloading;
- **commit authors' pictures** from Gravatar (**Settings ▸ Appearance** turns
it off) or GitHub;
- **GitHub requests** while you're signed in, and your diff to the **AI
provider** you connect, only when you ask.

Every connection, in full: [PRIVACY.md](PRIVACY.md).
10 changes: 7 additions & 3 deletions apps/desktop/build/compile-icon.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@
# Apple's grid expects — at dock size the old framing read as a small mark
# floating in a large empty square.
#
# NOTE: build/icon.icns comes from brand/gitstudio-dock-1024.png, NOT from this
# SVG, so it does not inherit the zoom. It is only used on macOS 11-15.
# NOTE: build/icon.icns comes from brand/gitstudio-dock-graphite-1024.png — the
# Graphite tile, which is this icon as macOS 26 draws it (see
# brand/gitstudio-icon-graphite.svg) — so a closed GitStudio looks the same on
# 11-15 as on 26, and the same as the running app in the default dark style
# (Settings ▸ Appearance ▸ Dark style; main.ts setDockIcon leaves the bundle's
# icon alone for Graphite). It is only used on macOS 11-15.

set -e
cd "$(dirname "$0")"
Expand All @@ -49,7 +53,7 @@ ISET="$OUT/icon.iconset"; mkdir -p "$ISET"
python3 - "$ISET" <<'PY'
import sys
from PIL import Image
src = Image.open("../../../brand/gitstudio-dock-1024.png").convert("RGBA")
src = Image.open("../../../brand/gitstudio-dock-graphite-1024.png").convert("RGBA")
for n in (16, 32, 128, 256, 512):
src.resize((n, n), Image.LANCZOS).save(f"{sys.argv[1]}/icon_{n}x{n}.png")
src.resize((n * 2, n * 2), Image.LANCZOS).save(f"{sys.argv[1]}/icon_{n}x{n}@2x.png")
Expand Down
Binary file modified apps/desktop/build/icon.icns
Binary file not shown.
5 changes: 5 additions & 0 deletions apps/desktop/esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ function copyStaticAssets() {
// dockIconPath) so a runtime theme swap never shrinks the icon.
"brand/gitstudio-dock-1024.png": "dock.png",
"brand/gitstudio-dock-light-1024.png": "dock-light.png",
// Dark style ▸ Graphite (shared/darkStyle.ts): the tile macOS draws for
// the closed app, for a dev build's Dock (its bundle icon is Electron's)
// and Settings' preview.
"brand/gitstudio-dock-graphite-1024.png": "dock-graphite.png",
"brand/gitstudio-icon-graphite-512.png": "icon-graphite.png",
"brand/gitstudio-icon.svg": "brand-icon.svg",
"brand/gitstudio-icon-light.svg": "brand-icon-light.svg",
"brand/gitstudio-wordmark-light.svg": "brand-wordmark-light.svg",
Expand Down
5 changes: 5 additions & 0 deletions apps/desktop/harness/check.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ const CASES = [
["row-meta-columns-align", "explore~type:git~key:Enter"],
["the-dock-reserve-tracks-the-dock", "changes~click:.dock-chevron"],
["changing-the-theme-keeps-what-you-typed", "settings"],
// Settings ▸ Appearance ▸ Dark style: Graphite (default) or Neon, for the
// window and the Dock; and a window opened on Neon is Neon throughout.
["the-dark-style-picks-the-window-and-the-dock", "settings"],
["the-neon-style-paints-from-its-tokens", "graph", { extra: "darkstyle=neon" }],
["the-launch-screen-covers-the-start-and-hands-off", "dashboard", { extra: "darkstyle=neon" }],
["a-compare-diff-that-fails-says-so", "compare~text:Changed%20files"],
["placeholders-fit-their-field", "orgs"],
["placeholders-fit-their-field", "branches"],
Expand Down
Loading
Loading