A configurable Git workflow controller for VS Code.
GitPusher lives entirely in the VS Code status bar. You configure your preferred Git workflow once — staging, committing, pulling, testing, pushing — and after that you run the whole thing from a single click, or from the Command Palette.
GitPusher does not invent one-click Git pushing. It is a thin,
transparent controller over the same git you already use, with every
step visible in its output channel and nothing destructive happening
without your say-so.
Most Git workflows are the same five or six commands run in the same order, every time: check for changes, stage, commit, pull, maybe run tests, push. GitPusher lets you define that sequence once per workspace and then collapses it into one status bar click, while still showing you exactly what ran and stopping cleanly the moment something needs your attention (a conflict, a failed test, a rejected push).
- Status bar first. A single
GitPusheritem shows your current branch and change count (GitPusher ↑ 3 | main) and updates automatically as you edit, stage, and commit. Click it to run your configured workflow. No floating windows, no custom dashboard. - Configurable workflow engine. Enable or disable each step
independently: stage all changes, commit, pull (merge or rebase), run
a test command, ask for confirmation. GitPusher never hardcodes
git add . && git commit && git push. - Three commit message modes. Ask every time, use a fixed message,
or let GitPusher generate a short message from the changed files
(e.g.
Update 3 files in srcinstead ofchanges). - Safe by default. GitPusher never force-pushes, deletes branches, auto-resolves conflicts, discards your changes, resets the repository, or rewrites history. If a pull/rebase produces conflicts, it stops immediately and offers to open the conflicted files — it does not try to guess a resolution.
- Per-workspace configuration. Settings are stored per workspace, so different repositories can have different remotes, branches, and workflows.
- Native VS Code UI throughout. Status bar, notifications, Quick Picks, input boxes, an output channel, and standard settings — nothing else.
- Build the
.vsix(see Development and Packaging below), or install a pre-built one. - In VS Code: Extensions view →
...menu → Install from VSIX... → selectgitpusher-0.1.0.vsix. - Open a folder that is (or will be) a Git repository. GitPusher will
offer to walk you through setup the first time you open the workspace
or run
GitPusher: Push.
Run GitPusher: Configure from the Command Palette, or click the status bar item for the first time, to walk through setup:
- Remote — which Git remote to push to (autodetected from
git remote, or entered manually). - Branch — always use the current branch (recommended), or pin to a specific branch name.
- Workflow steps — toggle: stage all changes, commit changes, pull before push, run tests before push, ask for confirmation.
- Commit message mode — ask every time, fixed message, or automatically generated.
- Pull strategy — rebase or merge (only asked if "pull before push" is enabled).
All of this maps directly to standard VS Code settings under the
gitpusher.* namespace (Settings UI or settings.json), so you can also
edit it by hand or per-workspace without re-running setup:
| Setting | Default | Description |
|---|---|---|
gitpusher.remote |
"origin" |
Remote to push to / pull from |
gitpusher.branch |
"" |
Fixed branch, or empty to always use the current branch |
gitpusher.stageAllChanges |
true |
Run git add --all before committing |
gitpusher.commitChanges |
true |
Create a commit as part of the workflow |
gitpusher.commitMessageMode |
"ask" |
ask | fixed | auto |
gitpusher.fixedCommitMessage |
"Update" |
Used when mode is fixed |
gitpusher.pullBeforePush |
true |
Pull (or rebase) before pushing |
gitpusher.pullStrategy |
"rebase" |
rebase | merge |
gitpusher.runTestsBeforePush |
false |
Run a test command before pushing |
gitpusher.testCommand |
"npm test" |
Command run when the above is enabled |
gitpusher.confirmBeforePush |
true |
Show a confirmation prompt before running |
gitpusher.configured |
false |
Internal flag set once setup has run |
With the defaults (stage, commit, pull --rebase, push, confirm), clicking the status bar item runs:
Detect changes
-> Stage all changes
-> Commit (message per your configured mode)
-> Pull --rebase from origin/main
-> Push to origin/main
Every step is echoed to the GitPusher output channel:
[GitPusher] 2026-09-20, 2:14:03 PM
Repository OK. Branch: main
Detected 3 modified, 0 staged, 0 untracked file(s).
Staged all changes.
Created commit: "Update auth flow"
Pulled from origin/main (rebase).
Pushed to origin/main.
Push completed successfully.
If you also enable "run tests before push," a runTests step is inserted
between the pull and the push, and a failing test stops the workflow
before anything is pushed.
All available from the Command Palette (Cmd/Ctrl+Shift+P):
| Command | Description |
|---|---|
GitPusher: Push |
Run the full configured workflow |
GitPusher: Push and Sync |
Same as Push (alias, for discoverability) |
GitPusher: Commit |
Stage (if enabled) and commit only, no pull/push |
GitPusher: Configure |
Open the setup flow |
GitPusher: Refresh Status |
Force a status bar refresh |
GitPusher: Show Output |
Open the GitPusher output channel |
GitPusher: Reset Configuration |
Clear all GitPusher settings for this workspace |
GitPusher: Open Conflicted Files |
Open every file with unresolved conflicts |
An optional keybinding (Ctrl+Alt+G Ctrl+Alt+P / Cmd+Alt+G Cmd+Alt+P)
runs GitPusher: Push; rebind it in Keyboard Shortcuts if it conflicts
with something in your setup.
GitPusher will never, under any configuration:
- Force push
- Delete branches
- Automatically resolve merge conflicts
- Discard uncommitted changes
- Reset the repository
- Rewrite history without you explicitly running that Git command yourself
If a pull or rebase produces conflicts, GitPusher stops immediately, shows "GitPusher stopped: merge conflicts detected", and offers a button to open every conflicted file. It does not attempt any further Git operations until you resolve them yourself.
A rejected push (non-fast-forward), a network failure, and an authentication failure are each detected and reported with a specific, readable message rather than a raw Git error dump — the full technical output always remains available in the output channel.
npm install
npm run compile # one-off build
npm run watch # incremental build while developingThen press F5 in VS Code (with this folder open) to launch an Extension
Development Host with GitPusher loaded.
npm testTests run against a fully in-memory fake of the Git layer
(GitManagerLike) — no real Git process is spawned and no real
repository is touched. Coverage includes: a clean repository, modified
files, staging (enabled/disabled), committing (all three message modes,
including a cancelled prompt), pulling, pushing, a rejected push, a
rebase conflict, a missing git binary, a workspace that isn't a
repository, an invalid/missing remote, and both outcomes of the
"run tests before push" gate.
npm install -g @vscode/vsce # if you don't already have it
npm run compile
vsce packageThis produces gitpusher-0.1.0.vsix in the project root. Install it with
Extensions → ... → Install from VSIX..., or:
code --install-extension gitpusher-0.1.0.vsixsrc/
extension.ts Activation, wiring, auto-refresh subscriptions
git/
gitManager.ts Controlled git CLI wrapper (execFile, fixed arg arrays)
gitStatus.ts Porcelain status parsing + snapshot assembly
gitCommands.ts Commit-message generation, test-command runner
workflow/
workflowEngine.ts Orchestrates steps in order, stops on failure
workflowSteps.ts Individual step implementations
config/
configManager.ts Wraps VS Code's configuration API
ui/
statusBar.ts Status bar item + its render states
setup.ts Native QuickPick/InputBox setup flow
notifications.ts Notification helper
commands/
commands.ts Command Palette registration + handlers
test/ Mocha unit tests (fake Git layer)
Why the Git CLI, not only the Git extension API: GitPusher subscribes
to the built-in vscode.git extension's repository state-change events
(repository.state.onDidChange) to refresh the status bar reactively,
without polling the filesystem. Mutating operations (stage, commit,
pull, push, rebase) are run through child_process.execFile('git', [...])
with a fixed, whitelisted argument array per call — never a shell string
— so no user-controlled value (branch name, remote name, commit message)
can be interpreted as an extra flag. The one exception is the optional
"run tests before push" step, which necessarily runs an arbitrary,
user-configured shell command; everything else is a closed set of Git
subcommands GitPusher itself constructs.
- The keyboard shortcut for
GitPusher: Pushis unbound to any specific editor focus context, so it may need rebinding on some keymaps. - Auto-generated commit messages use lightweight file-path heuristics, not an AI-generated summary of the diff content.
- Multi-root workspaces are supported by re-reading the first workspace folder when the folder list changes; running two independent GitPusher workflows against two roots simultaneously isn't a supported scenario.
- The status bar item's "Pushed" success state is time-based (reverts to idle a few seconds later) rather than tied to a VS Code event, since no such event exists for "the user has seen this."