Psychopathic Git Shorcuts

if type brew &>/dev/null; then
    FPATH=$(brew --prefix)/share/zsh-completions:$FPATH
    autoload -Uz compinit
    compinit
  fi

#compdef gt
###-begin-gt-completions-###
#
# yargs command completion script
#
# Installation: gt completion >> ~/.zshrc
#    or gt completion >> ~/.zprofile on OSX.
#
_gt_yargs_completions()
{
  local reply
  local si=$IFS
  IFS=$'
' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" gt --get-yargs-completions "${words[@]}"))
  IFS=$si
  _describe 'values' reply
}
compdef _gt_yargs_completions gt
###-end-gt-completions-###

# gh completions
fpath=($HOME/.zsh/completions $fpath)
autoload -Uz compinit
compinit

# Determine defaultBranch once per repo, store it if not set
get_default_branch() {
  local branch
  branch=$(git config --get bakert.defaultBranch 2>/dev/null)

  if [[ -z "$branch" ]]; then
    branch=$(git remote show origin 2>/dev/null | awk '/HEAD branch/ {print $NF}')
    branch=${branch:-master}

    git config --local bakert.defaultBranch "$branch"
    echo "Set bakert.defaultBranch to '$branch' in local git config" >&2
  fi

  echo "$branch"
}

# Perform an operation that might fail if the current branch is implicated in a way that won't fail
# Leaves you on default branch after if your current branch ceased to exist.
with_default_branch() {
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  local default_branch=$(get_default_branch)

  if [[ "$current_branch" != "$default_branch" ]]; then
    git switch "$default_branch"
  fi

  "$@"

  if [[ "$current_branch" != "$default_branch" ]] && git show-ref --verify --quiet "refs/heads/$current_branch"; then
    git switch "$current_branch"
  fi
}

## Functions not aliases to allow completions
ga()    { git add "$@"; }; compdef _git ga=git-add
gaa()   { git add . "$@"; }; compdef _git gaa=git-add
# Equivlent to `git add !$`
gal() {
  emulate -L zsh
  setopt noglob

  local cmd last
  cmd=$(fc -ln -1) || return 1
  local -a words
  words=(${(z)cmd})
  (( ${#words} )) || { echo "No history."; return 1; }

  last=${words[-1]}
  last=${(Q)last}       # remove surrounding quotes if any

  # Expand ~ / ~user without enabling globbing
  if [[ $last == "~"* ]]; then
    last=${~last}
  fi

  [[ -n $last ]] || { echo "No last arg."; return 1; }
  git add -- "$last"
}; compdef _git gal=git-add
gap()   { git add -p "$@"; }; compdef _git gap=git-add
gb()    { git branch "$@"; }; compdef _git gb=git-branch
gbd()   { with_default_branch git branch -D "$@"; }; compdef _git gbd=git-branch
gbl()   { git blame "$@"; }; compdef _git gbl=git-blame
gc()    { git commit "$@"; }; compdef _git gc=git-commit
gca()   { git commit --amend "$@"; }; compdef _git gca=git-commit
gcae()  { git commit --amend --no-edit "$@"; }; compdef _git gcae=git-commit
gcan()  { git commit --amend -n "$@"; }; compdef _git gcan=git-commit
gcane() { git commit --amend -n --no-edit "$@"; }; compdef _git gcane=git-commit
gclb()  { gpru && gded }; compdef _git gclb=git-branch
gclfd() { git clean -fd "$@" }; compdef _git gclfd=git-clean
gcp()   { git cherry-pick "$@" }; compdef _git gcp=git-cherry-pick
gcpa()  { git cherry-pick --abort "$@" }; compdef _git gcpa=git-cherry-pick
gcpc()  { git cherry-pick --continue "$@" }; compdef _git gcpa=git-cherry-pick
glc()   { git clone "$@"; }; compdef _git glc=git-clone
gcm()   { git commit -m "$@"; }; compdef _git gcm=git-commit
gcn()   { git commit -n "$@"; }; compdef _git gcn=git-commit
gco()   { git checkout "$@"; }; compdef _git gco=git-checkout
gd()    { git diff "$@"; }; compdef _git gd=git-diff
gdc()   { git diff --cached "$@"; }; compdef _git gdc=git-diff
gdd()   { git diff $(get_default_branch) "$@"; }; compdef _git gdd=git-diff
# Delete all local branches that don't have changes not already in default branch
gded() {
  local default_branch=$(get_default_branch)
  for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
    if [[ "$branch" != "$default_branch" ]]; then
      local count=$(git rev-list --count "$branch" --not "$default_branch")
      if [[ "$count" -eq 0 ]]; then
        echo "Deleting branch: $branch"
        git branch -D "$branch"
      fi
    fi
  done
}
gfo()   { git fetch origin $(get_default_branch):$(get_default_branch) "$@"; }; compdef _git gfo=git-fetch
# Make a gist, guessing exactly what you want a gist of based on state of repo
gg() {
local target=$1
  local desc=""
  local filename=""
  local url=""

  if [[ -z $target ]]; then
    if [[ -n $(git status --porcelain) ]]; then
      desc="Working copy diff"
      filename="working.diff"
      url=$((git diff HEAD && git ls-files --others --exclude-standard | xargs -I {} git diff /dev/null {}) | gh gist create -f "$filename" -d "$desc" - | tail -n1)
    else
      desc="Top commit diff (HEAD)"
      filename="head.diff"
      url=$(git show HEAD | gh gist create -f "$filename" -d "$desc" - | tail -n1)
    fi
  elif [[ $target == "develop" ]]; then
    desc="Diff from develop"
    filename="develop.diff"
    url=$(git diff develop...HEAD | gh gist create -f "$filename" -d "$desc" - | tail -n1)
  else
	desc="Diff of $target"
	filename="$target.diff"
	url=$(git diff "$target...HEAD" | gh gist create -f "$filename" -d "$desc" - | tail -n1)
  fi

  echo "$url"
  open "$url"
}; compdef _git gg=git-show
# Make a gist of the difference between working copy and default branch
ggd() { gg "$(get_default_branch)"; }; compdef _git ggd=git-show
gl()  { git log "$@"; }; compdef _git gl=git-log
# Pretty one-liner log
glp() {
  local git_args=()
  if [[ $1 =~ ^-[0-9]+$ ]] || [[ $1 =~ ^--max-count=[0-9]+$ ]] || [[ $1 =~ ^-n$ && $2 =~ ^[0-9]+$ ]]; then
    git_args=("$@")
  else
    git_args=("$@")
  fi
  git log --pretty="tformat:$FORMAT" "${git_args[@]}" |
  column -t -s '{' |
  less -XRS --quit-if-one-screen
}; compdef _git glp=git-log
gm()   { git mv "$@"; }; compdef _git gm=git-mv
gp()   { git pull "$@"; }; compdef _git gp=git-pull
gpf()  { git push --force-with-lease "$@"; }; compdef _git gpf=git-push
gpr()  { gh pr create "$@"; }; compdef _gh gpr=gh-pr
gprb()  { gh pr create -B "$@"; }; compdef _gh gprb=gh-pr
gprd()  { gh pr create -d "$@"; }; compdef _gh gprd=gh-pr
gprdb() { gh pr create -d -B "$@"; }; compdef _gh gprdb=gh-pr
# Remove local branches that aren't on remote any more
gpru() {
  cleanup_gone_branches() {
    git remote update origin --prune
    local gone_branches=$(git branch -vvv | grep gone | cut -d' ' -f3)
    if [[ -n "$gone_branches" ]]; then
      echo "$gone_branches" | xargs -I{} git branch -D '{}'
    fi
  }
  with_default_branch cleanup_gone_branches
}
gpso()  { git push --set-upstream origin "${@:-$(git branch --show-current)}"; }; compdef _git gpso=git-push
grb()   { git rebase "$@"; }; compdef _git grb=git-rebase
grba()  { git rebase --abort "$@"; }; compdef _git grba=git-rebase
grbc()  { git rebase --continue "$@"; }; compdef _git grbc=git-rebase
grbd()  { git rebase $(get_default_branch) "$@"; }; compdef _git grbd=git-rebase
grbdo() { gfo && git rebase $(get_default_branch) "$@"; }; compdef _git grbd=git-rebase
grbi()  { git rebase -i $(get_default_branch) "$@"; }; compdef _git grbi=git-rebase
grl()   { git reflog "$@"; }; compdef _git grl=git-reflog
grs()   { git reset "$@"; }; compdef _git grs=git-reset
grsh1() { git reset HEAD~1 "$@"; }; compdef _git grsh1=git-reset
grsh2() { git reset HEAD~2 "$@"; }; compdef _git grsh2=git-reset
grsh3() { git reset HEAD~3 "$@"; }; compdef _git grsh3=git-reset
grsh4() { git reset HEAD~4 "$@"; }; compdef _git grsh4=git-reset
grsh5() { git reset HEAD~5 "$@"; }; compdef _git grsh5=git-reset
grsh6() { git reset HEAD~6 "$@"; }; compdef _git grsh6=git-reset
grsh7() { git reset HEAD~7 "$@"; }; compdef _git grsh7=git-reset
grsh8() { git reset HEAD~8 "$@"; }; compdef _git grsh8=git-reset
grsh9() { git reset HEAD~8 "$@"; }; compdef _git grsh9=git-reset
grt()   { git restore "$@"; }; compdef _git grt=git-restore
grta()  { git restore . "$@"; }; compdef _git grt=git-restore
grts()  { git restore --staged "$@"; }; compdef _git grt=git-restore
grtsa() { git restore --staged . "$@"; }; compdef _git grt=git-restore
grm()   { git rm "$@"; }; compdef _git grm=git-rm
gs()    { git status "$@"; }; compdef _git gs=git-status
gsh()   { git show "$@"; }; compdef _git gsh=git-show
gshn()  { git show --name-only "$@"; }; compdef _git gsh=git-show
gst()   { git stash "$@"; }; compdef _git gst=git-stash
gstd()  { git stash drop "$@"; }; compdef _git gstd=git-stash
gstl()  { git stash list "$@"; }; compdef _git gstl=git-stash
gstp()  { git stash pop "$@"; }; compdef _git gstp=git-stash
gsts()  { git stash show -p "$@"; }; compdef _git gsts=git-stash
gstu()  { git stash -u "$@"; }; compdef _git gstu=git-stash
gsw()   { git switch "$@"; }; compdef _git gsw=git-switch
gswc()  { git switch -c "$@"; }; compdef _git gswc=git-switch
gswcd() { git switch -c "$1" $(get_default_branch); }; compdef _git gswcd=git-switch
gswd()  { git switch $(get_default_branch); }; compdef _git gswd=git-switch
gswp()  { git switch - "$@"; }; compdef _git gswd=git-switch
gtc()   { gt create "$@"; }
gtl()   { gt log "$@"; }
gtm()   { gt move "$@"; }
gtr()   { gt restack "$@"; }
gts()   { gt submit "$@"; }
gtsy()  { gt sync "$@"; }
gtt()   { gt track "$@"; }
alias gwip='git add . && git commit -m "WIP" -n'

Sort committers by average length of commit message

git log --no-merges --pretty=format:'COMMIT_START|%an|%B|COMMIT_END' | \
awk '
BEGIN { RS = "COMMIT_END\n"; FS = "|" }
/COMMIT_START/ {
    author = $2
    message = ""
    for (i = 3; i <= NF; i++) {
        if (i > 3) message = message "|"
        message = message $i
    }
    len = length(message)
    authors[author] += len
    counts[author]++
    if (!min[author] || len < min[author]) min[author] = len
    if (len > max[author]) max[author] = len
}
END {
    for (author in authors) {
        avg = authors[author] / counts[author]
        printf "%6.1f|%-30s|(min: %d, max: %d, commits: %d)\n",
               avg, author, min[author], max[author], counts[author]
    }
}' | sort -t'|' -k1 -nr | awk -F'|' '{printf "%-30s %s chars %s\n", $2, $1, $3}'

Gradient Borders with Transparent Background

<html lang="en">
<head>
<title>Gradient borders with transparent background</title>
<meta charset="utf-8">
<style>
* {
  box-sizing: border-box;
}

body {
  background-color: black;
  color: white;
}

.card {
  background-color: gray;
  color: black;
}

.gradient-border-mask {
  display: flow-root;
  position: relative;
  padding: 1.3rem;
}

.gradient-border-mask::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: 5px;
  border: 5px solid transparent;
  background: linear-gradient(45deg, purple, orange) border-box;
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: destination-out;
  mask-composite: exclude;
}
</style>

</head>
<body>

<div class="gradient-border-mask">
  <p>Lorem ipsum dolor sit amet consectetur</p>
</div>

<div class="card">
  <p>Lorem ipsum dolor sit amet consectetur</p>
  <div class="gradient-border-mask">
    <p>Lorem ipsum dolor sit amet consectetur</p>
  </div>
</div>

</body>
</html>

How to keep your input and dismiss/cancel atuin

The normal behavior of atuin is to put either the command you matched onto your commandline, or nothing. So if you Ctrl-r and type something with no good match and exit, you “lose” what you have typed. You can Ctrl-g to get back what you had when you pressed Ctrl-r but anything you typed after that is lost.

To get what I think is superior behavior set exit_mode = "return_query" in ~/.config/atuin/config.toml. Now whatever is in the atuin buffer is now on your commandline if you hit Esc. You can still Ctrl-g to get what you had before Ctrl-r or Ctrl-c to exit to an empty commandline.

Starting more than one dev webserver each in its own terminal window (Mac)

#!/usr/bin/env zsh
# Script to start monorepo development processes in separate terminals
open_position_run() {
  local dir=$1
  local cmd=$2

  # Start the server
  osascript -e 'tell application "Terminal"
    do script "cd '"$dir"' && nvm use 20 && '"$cmd"' &" in window 1
  end tell'
}

open_position_run "/Users/bakert/monorepo/apps/app1 "pnpm dev"
open_position_run "/Users/bakert/monorepo/apps/app2 "pnpm dev"

History (Fourth Time)

I did this in 2008, 2011 and 2015 but forgot to do it for ten years.

[zarniwoop ~] history 0 | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn  | head
34675 git
5294 composer
4376 cd
3761 vi
3076 pnpm
2914 python
2188 m
1917 ls
1822 python3
1717 ssh

Compared to 2015. New: composer, pnpm, python/python3, m (run scripts for an app I work on). Climbers: git, cd. Fallers: ssh, ls. Old: c, php, pass, sudo, ruby.

COUNT(*) OVER () in Drizzle

In general I like to use COUNT(*) OVER () to get the total count for a query when retrieving a slice with OFFSET and LIMIT (very useful for pagination) rather than issuing a separate query for the total count. This is not super well supported in Drizzle but you can do it like this:

const data = await db.query.tableName.findMany({
    …
    extras: {
        // Weird cast here because COUNT(*) is a bigint which is handled as a string in js
        // https://orm.drizzle.team/docs/guides/count-rows
        total: sql<number>`CAST(COUNT(*) OVER() AS INTEGER)`.as("total"),
    },
    …

Set Up a New Mac (May 2025 Edition)

Previously: July 2019, July 2022, August 2023

  • Upgrade to latest MacOS
  • Restore from Blackblaze backup: u directory, dotfiles, .atuin dir, .config dir, .cursor dir, .nvm-zsh dir, .ssh dir, .vim dir, any other dot dirs that look useful, ~/Library/Application Support/Alfred
  • Set perms on .ssh
    $ cd ~ && chmod 600 ~/.ssh/* && chmod 700 ~/.ssh && chmod 644 ~/.ssh/*.pub
    
  • Set perms on ~/u/bin
    $ chmod u+x ~/u/bin/*
    
  • Hide Desktop icons
    $ defaults write com.apple.finder CreateDesktop false
    $ killall Finder
    
  • Show hidden files in Finder with Cmd-Shift-.
  • 1Password
  • Dock: remove everything, hiding on, magnification on
  • Alfred (and give it Accessibility access, add license key)
  • System Settings, Mouse, set Trackpad speed to max and enable right-click
  • Sublime Text 4 (add license key, set "trim_trailing_white_space_on_save": "all" in sublime prefs, install Package Control, install Nord Theme via Package Control)
  • subl commandline sublime.
    $ ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" ~/u/bin/subl
  • sublime git-ignorer. (1) add Package Control repo https://github.com/apc999/sublime-text-gitignore (2)
    install package sublime-text-gitignore (3) use menu item : File->Exclude Git-ignored (4) Give this a keyboard shortcut in Sublime, Preferences, Key Bindings with { "keys": ["super+shift+i"], "command": "exclude_ignored" }
  • Keyboard shortcut to toggle word wrap in Sublime Text. Preferences, Key Bindings { "keys": ["super+shift+w"], "command": "toggle_setting", "args": { "setting": "word_wrap" } }
  • Install FiraCode and add it to Sublime Text prefs with "font_face": "Fira Code".
  • Nord theme for Terminal and make default in preferences.
  • Polar theme for terminal when ssh’ing to remotes
  • For both Nord and Polar themes: “Use Option as Meta Key” in Terminal to make left Alt work as Esc. And Terminal, Settings, Advanced, un-check “Audible bell” and “Only when sound is muted”. And Shell, (When the shell exits) “Close the window”.
  • System Preferences, Sound, turn “Alert volume” all the way down
  • Use Ctrl-f7 to enable keyboard navigation of dialogs
  • Homebrew. (Installs OSX commandline tools)
  • Discord
  • Change all .txt to open with Sublime Text
  • WhatsApp
  • Chrome. Sign in to Chrome to get extensions, then tell it you really do want uBlock Origin via “Keep for Now” under Extensions in Settings. Uninstall Chrome if they’ve finally locked it down entirely
  • Firefox. Sign in to sync extensions. Set as default browser. Settings, search for “Autoplay”, Settings, Allow Audio and Video. Visit each extension you want in Private Browsing and select Run in Prviate Windows
  • Skitch
  • Backblaze. Choose to inherit the previous backup (it won’t copy anything down). Give System Settings, Privacy & Security, Full Disk Access
  • Parallels Desktop + Windows + MTGO
  • Disable Ask Siri in System Preferences, Siri
  • Turn on “tap to click” in System Preferences, Trackpad
  • Disable long-press (it’s annoying when selecting text in Chrome): defaults write -g ApplePressAndHoldEnabled -bool false
  • Spotify
  • Slack
  • Rectangle Pro
  • DaisyDisk
  • ChatGPT
  • Claude
  • Linear
  • Zed
  • Notion
  • brew install nvim
  • brew install mariadb
  • brew install npm
  • brew install pnpm@9
  • brew install apache2.
  • brew install php. Enable in Apache with LoadModule, FilesMatch and DirectoryIndex directives as per homebrew output and brew services restart apache2.
  • brew install gh
  • brew install composer
  • brew install bat
  • brew install atuin && atuin import auto
  • brew install delta
  • brew install vercel-cli
  • npm install -g rtm-cli
  • git clone important repos (ff, pd, monorepo)
  • Restore any local databases for dev (ff, decksite, logsite)
  • ln -s ~/ff/src/www /opt/homebrew/var/www/ff
  • GRANT ALL ON ff.* TO ff@localhost IDENTIFIED BY *REDACTED*
  • pd setup
  • Check open but unsaved files in Sublime Text in case there’s anything you need to preserve
  • git status in any recent repos and check for uncommitted work.

zsh “shortcuts”

$ cat ~/.config/zsh/nav.zsh 
───────┬─────────────────────────────────────────────────────────────────────
       │ File: /Users/bakert/.config/zsh/nav.zsh
───────┼─────────────────────────────────────────────────────────────────────
   1   │ export MONOREPO_ROOT="/Users/bakert/cardeio-monorepo-v2"
   2   │ export ORGANIZED_PLAY="$MONOREPO_ROOT/apps/organized-play"
   3   │ export PLAY_NEXT="$MONOREPO_ROOT/apps/play-next"
   4   │ export LUDWIG="$MONOREPO_ROOT/apps/ludwig"
   5   │ export CARD_SEARCH_DEMO="$MONOREPO_ROOT/apps/card-search-demo"
   6   │ export DECK_BUILDER="$MONOREPO_ROOT/packages/deck-builder"
   7   │ 
   8   │ hash -d mr="$MONOREPO_ROOT"
   9   │ hash -d op="$ORGANIZED_PLAY"
  10   │ hash -d pn="$PLAY_NEXT"
  11   │ hash -d lw="$LUDWIG"
  12   │ hash -d cs="$CARD_SEARCH_DEMO"
  13   │ hash -d db="$DECK_BUILDER"
───────┴──────────────────────────────────────────────────────────────────────

Use prefixed with ~ anywhere you need a path:

$ cd ~mr
$ vi ~lw/src/index.ts

Git – You’re Doing It Wrong

Instead ofDo this
git checkout {file}git restore {file}
git checkout {branch}git switch {branch}
git checkout -b {newbranch}git switch -c {newbranch}
git push --forcegit push --force-with-lease
git rebasegit rebase --update-refs