Bash shortcuts around git worktree and related flows (work script).
Working on several issues at once usually means multiple working trees: one long-lived clone plus extra checkouts so each branch has its own directory. The underlying Git commands are powerful but awkward day to day: long git worktree add lines, remembering two different paths (the “main” repo vs each worktree), fetching and grepping remotes/origin/... to find the right branch, and switching shells into the right folder after each add.
git-work is a small Bash layer on top of that: you configure one main clone (MAIN_PATH) and one parent directory for all issue worktrees (BRANCHES_PATH). With JIRA_BASE set, the same branch names tie together opening the ticket (work details), discovering what exists on origin (work checkout after a fetch), landing in the right tree (work + grep / work main), and shipping changes (work push).
Remote branches are expected to carry your issue id in the name (for example ABC123-fix-login). work checkout uses that naming: it fetches, shows matching remotes/origin/... lines, then adds a worktree under BRANCHES_PATH after you confirm. From a tree (or after jumping with work 123), work details builds JIRA_BASE + id and opens the browser; work push pushes the current branch from whatever directory you are in (still using MAIN_PATH as the git hub). work with no args lists what is already checked out locally.
- One-time: configure
.env(includingJIRA_BASEif you use Jira links), runwork init(directories, clone if needed, install thework()shell wrapper). - Often:
worklists what is already checked out;work 123jumps to the matching issue directory;work main(or yourWORK_MAIN_ALIAS) returns to the main clone;work details(optionally with the same grep) opens the ticket in the browser from the branch name. - New branch on disk:
work checkout 456fetches fromorigin, shows matching remote branches, then runsgit worktree addunderBRANCHES_PATHafter you confirm (and cancdthere whenAUTO_CD_AFTER_CHECKOUT=true). - Ship: from inside a worktree,
work pushpushes the current branch toorigin(setting upstream when needed).
The blocks below are fabricated examples of the shape of real output; your paths, prefixes, and counts will differ.
Bare work (list checked-out worktrees under BRANCHES_PATH):
Checked out branches (3):
[M] modified working tree [A] ahead of upstream [B] both [C] clean
ISSUES:
ABC123-login-spinner [M]
ABC127-api-timeout [C]
RELEASES:
release-2.4 [C]
OTHER:
spike-json-parser [A]
For the base branch type main
work checkout (fetch, list remotes grouped like the bare list, then confirm before git worktree add — only proceeds when exactly one remote branch matches):
Fetching from origin...
Listing available / matching branches
ISSUES:
ABC123-login-spinner
RELEASES:
OTHER:
Will run the following in (/home/you/projects/acme-app):
git worktree add /home/you/trees/acme/ABC123-login-spinner ABC123-login-spinner
Does it look OK? (y/n): y
work 123 when exactly one issue directory matches (wrapper ends up cd-ing into that tree):
(silent — your prompt moves to BRANCHES_PATH/ABC123-login-spinner)
work details (from a branch whose name contains the issue id; uses JIRA_BASE):
Opening JIRA issue: ABC123
URL: https://jira.example.com/browse/ABC123
work push (fabricated — real output is plain git push):
Enumerating objects: 12, done.
Counting objects: 100% (12/12), done.
...
To https://github.com/acme/app.git
abc1111..def2222 ABC123-login-spinner -> ABC123-login-spinner
- Bash-only: The
workscript targets Bash.work initappends awork()function to~/.bashrc(orWORK_BASHRCin.env). - Requires local config: You must create
.envbeside theworkscript (from.env.template). Nothing runs without it. - Git conventions: Listing and checkout flows assume a typical
originremote layout (remotes/origin/...). Adjust your workflow or script if you use different remote names. - Not a general Git UI: This is a small helper for worktrees and issue-style branch names, not a replacement for
gititself.
After work init, a work() function is appended to ~/.bashrc (or WORK_BASHRC in .env). It runs the work script from this checkout and applies the post-command cd behavior.
Open a new terminal or run:
source ~/.bashrcUntil you run init, use ./work from the clone.
- Copy
.env.templateto.envnext toworkand fill in GIT_REPO, BRANCHES_PATH, MAIN_PATH, and PROJ_PREFIX or PROJ_PREFIXES (seeworkconfiguration). Add JIRA_BASE if you will usework details. - Run
./work init— createsBRANCHES_PATH, clones intoMAIN_PATHonly when that path is missing or an empty directory (skips clone if a repo is already there), and installs or refreshes thework()wrapper in your bashrc (safe to re-run; re-run after moving this repo).
Run work --help (or work -h) for the full command list and usage text.
Copy .env.template to .env in the same directory as the work script.
Required:
GIT_REPO— Remote URLwork inituses to clone the main repo intoMAIN_PATHwhen that tree is missing.BRANCHES_PATH— Parent directory for worktrees created bywork checkout/work create.MAIN_PATH— Path to the main clone (default git context for list, fetch, push, and related commands).PROJ_PREFIXorPROJ_PREFIXES— At least one must be set: use PROJ_PREFIX for a single issue key (e.g.ABC), or PROJ_PREFIXES for an ERE alternation (e.g.ABC|DEF|GHI) when you have multiple keys; if PROJ_PREFIXES is non-empty it is used for issue-id detection instead of PROJ_PREFIX.
Optional (or needed for specific commands):
JIRA_BASE— Base URL for your issue tracker;work detailsappends the extracted issue id. Set this if you usework details.AUTO_CD_AFTER_CHECKOUT— When set totrue, after a successfulwork checkoutorwork createthe wrapper records the new worktree path so your shellcds there automatically. If unset or nottrue, that automaticcddoes not happen (post-worktree hooks still run when configured).WORK_MAIN_ALIAS— keyword forwork <keyword>to jump to the main clone (MAIN_PATH). Default ismain; set tocode,master, etc. if you prefer.RELEASE_PREFIX— prefix used to identify release branches (defaultrelease). Used for theRELEASESlist and for matching release branches inwork checkout.WORK_POST_WORKTREE_DIR— directory of scripts to run after a successfulwork checkoutorwork create. Relative paths are resolved from this git-work clone (next to theworkscript); use an absolute path to point elsewhere. Default.work/post-worktree.d— commit that folder here so hooks follow your tooling clone. Executable files and*.shfiles run in sorted order (e.g.10-foo.sh,20-bar). Environment:WORK_WORKTREE_PATH,WORK_HOOK_REASON(checkoutorcreate). If the directory is missing, nothing runs. A failing hook is reported on stderr; the worktree is still created.WORK_BASHRC— file wherework initappends thework()block (default~/.bashrc).
The work() wrapper communicates the directory to cd into via a fixed file under /tmp/last_worktree_path_goto, which is then evaluated in the shell. On shared machines, /tmp symlink races are theoretically possible. Use this tool in environments you trust, or harden locally (for example by changing the script to use a private path under $XDG_RUNTIME_DIR or $HOME).
To report security issues privately, see SECURITY.md.
This project is licensed under the MIT License — see LICENSE.
See CONTRIBUTING.md.
Suggested repository topics: git, worktree, bash, developer-tools, shell. Set the repository description to the opening tagline under the title (or equivalent one-liner).