Fish & Gits
I’ve been using the Fish shell for a while, and it’s really gotten to the point where I miss it when I can’t use it :)
To share with folks, here are some of my Fish configurations and Git configs that make my life as a Blender developer easier.
This post was made possible by the Blender Development Fund.
Fish Config
Update 2024-04-03: I’ve started to track the pull request related functions my projects.blender.org profile space. Go there to get the latest versions.
These I store in ~/.config/fish/conf.d/aliases.fish
:
set BLENDER_BUILD_ROOT /home/sybren/workspace/blender-git
set FLAMENCO_ROOT /home/sybren/workspace/blender/flamenco-3
function cdf -d "CD to Flamenco directory"
cd $FLAMENCO_ROOT
end
function cdlibs -d "CD to Blender libs directory"
cd $BLENDER_BUILD_ROOT/lib
end
function cddeps -d "CD to Blender deps directory"
cd $BLENDER_BUILD_ROOT/build_deps/deps
end
function cdbuild -d "CD to Blender release build directory"
cd $BLENDER_BUILD_ROOT/build_linux
end
function cddebug -d "CD to Blender debug build directory"
cd $BLENDER_BUILD_ROOT/build_debug
end
function cdsrc -d "CD to Blender source directory"
cd $BLENDER_BUILD_ROOT/blender
end
function cdtracker -d "CD to Blender bug tracker directory"
cd $BLENDER_BUILD_ROOT/tracker
end
function cddocs -d "CD to Blender developer docs and activate the venv"
cd $BLENDER_BUILD_ROOT/developer-docs
. ./.venv/bin/activate.fish
end
function cdmanual -d "CD to Blender manual and activate the venv"
cd $BLENDER_BUILD_ROOT/manual
. ./.venv/bin/activate.fish
end
function _makebranch -a BRANCH
cdsrc; or return 1
printf "\033[95mChecking out branch \033[96m$BRANCH\033[0m\n"
git co $BRANCH; or return 2
printf "\033[95mPulling branch \033[96m$BRANCH\033[0m\n"
git pull; or return 5
printf "\033[95mmake update\033[0m\n"
make update; or return 3
printf "\033[95mBuilding Blender\033[0m\n"
bb; or return 4
printf "\033[95mBuilt $BRANCH\033[0m\n"
end
function mm -d "Make Main, update & build Blender main branch, release mode"
_makebranch main
end
function mmb -d "Make Main, then run Blender"
_makebranch main; and blender --open-last $argv
end
function mr -d "Make release branch"
cdsrc
set branch (git branch -r --list 'origin/blender-v*-release' | sort -n | tail -n 1 | sed 's+.*origin/++')
printf "\033[95mSwitching to release branch\033[0m \033[96m$branch\033[0m\n"
_makebranch $branch
end
function bb -d "Build Blender, release mode"
nice -n 1 ninja -C $BLENDER_BUILD_ROOT/build_linux/ $argv; or return $status
nice -n 1 ninja -C $BLENDER_BUILD_ROOT/build_linux/ install
end
function bbb -d "Build Blender and run with last file"
bb && blender --open-last $argv
end
function bbd -d "Build Blender, debug mode"
nice -n 1 ninja -C $BLENDER_BUILD_ROOT/build_debug/ $argv; or return $status
nice -n 1 ninja -C $BLENDER_BUILD_ROOT/build_debug/ install
end
function bbbd -d "Build Blender in Debug mode and run with last file"
bbd && blenderdebug --open-last $argv
end
function bbt -d "Build Blender, Clang-Tidy mode"
nice -n 1 ninja -C $BLENDER_BUILD_ROOT/build_tidy/ $argv
end
function bbr -d "Build Blender, release branch"
nice -n 1 ninja -C $BLENDER_BUILD_ROOT/build_release/ $argv
end
function cdb
set BLENDVER (blender --version | grep '^Blender' | cut -d' ' -f2 | sed 's/\\([0-9]\\+\\.[0-9]\\+\\).*/\\1/')
echo "Blender version: $BLENDVER"
cd ~/.config/blender/$BLENDVER
end
function git_rebase_onto_main
read -P "Rebase onto main? ENTER for yes, CTRL+C for no."; or begin
printf "\033[94mNot rebasing, the work is done.\033[0m\n"
return
end
git rebase main; and git submodule foreach git pull --rebase origin main
end
function svnadd -a SUBDIR -d "Add new files and remove deleted files"
# This is the Fish way of doing `SVN_STATUS=$(<svn status $SUBDIR)`
begin; set -l IFS; set SVN_STATUS (svn status $SUBDIR); end
echo "$SVN_STATUS" | grep '^\? ' | sed 's/^.//' | xargs --no-run-if-empty -n 1 svn add
echo "$SVN_STATUS" | grep '^\! ' | sed 's/^.//' | xargs --no-run-if-empty -n 1 svn rm
end
function pr -d "Pull in a Blender pull request"
# Set defaults
set _flag_owner blender
set _flag_repo blender
argparse 'o/owner=' 'r/repo=' -- $argv
or return 48
# Check for -r owner/repo notation:
set _flag_combined (echo "$_flag_repo" | string split /)
set _num_combined (count $_flag_combined)
if [ $_num_combined -gt 1 ]
set _flag_owner $_flag_combined[1]
set _flag_repo $_flag_combined[2]
end
set PRNUM $argv[1]
set JSON "pr-$PRNUM.json"
set URL "https://projects.blender.org/api/v1/repos/$_flag_owner/$_flag_repo/pulls/$PRNUM"
if ! curl --fail --no-progress-meter -o$JSON $URL
printf "\033[91mError fetching $URL\033[0m\n"
return 49
end
# Sanity check we can read the result
if ! jq <$JSON >/dev/null
printf "\033[91mCannot parse JSON at $JSON\033[0m\n" >&2
return 50
end
set PR_STATUS (jq -r .state <$JSON)
if [ (jq -r .merged <$JSON) = "true" ]
printf "\033[92mPR is already merged, check $URL\033[0m\n"
echo "Merged at:" (jq -r .merged_at <$JSON)
echo "Merged by:" (jq -r .merged_by.full_name <$JSON)
return 51
end
if [ (jq -r .state <$JSON) = "closed" ]
printf "\033[91mPR is closed, check $URL\033[0m\n"
return 50
end
set PR_NUM (jq -r .number <$JSON)
set PR_TITLE (jq -r .title <$JSON)
printf "\033[95mPulling #$PR_NUM: $PR_TITLE\033[0m\n"
set PR_REPO (jq -r .head.repo.full_name <$JSON) # "ChrisLend/blender"
set PR_AUTHOR (jq -r .head.repo.owner.username <$JSON) # "ChrisLend"
set PR_BRANCH (jq -r .head.ref <$JSON) # "vertical_scrolling_offscreen"
set PR_BASE_BRANCH (jq -r .base.ref <$JSON) # "main" or "blender-v3.5-release"
set LOCAL_BRANCH "PR/$PRNUM/$PR_AUTHOR-$PR_BRANCH"
printf "\033[90mIncoming branch: $PR_REPO\033[0m\n"
printf "\033[90mBase branch : $PR_BASE_BRANCH\033[0m\n"
printf "\033[90mLocal branch : $LOCAL_BRANCH\033[0m\n"
rm -f $JSON
set CURBRANCH (git branch --show-current 2>/dev/null)
if test "$CURBRANCH" != "$PR_BASE_BRANCH";
git checkout $PR_BASE_BRANCH
end
if git branch | grep -q $LOCAL_BRANCH;
printf "\033[95mBranch $LOCAL_BRANCH exists, going to refresh it\033[0m\n"
git branch -D $LOCAL_BRANCH
else
printf "\033[96mBranch $LOCAL_BRANCH does not exist\033[0m\n"
end
git checkout -b $LOCAL_BRANCH $PR_BASE_BRANCH; or return 47
git pull --no-rebase --ff --no-edit --commit https://projects.blender.org/$PR_REPO $PR_BRANCH; or return 48
printf "\033[95mBranch $LOCAL_BRANCH is ready for use\033[0m\n"
printf "\033[94mPulled #$PR_NUM: $PR_TITLE\033[0m\n"
end
function prprune -d "Delete all PR/* branches"
set BRANCHES (string trim (git branch | grep '^ PR/'))
if test -z "$BRANCHES";
echo "No PR branches to prune"
return 0
end
git branch -D $BRANCHES
end
function ffmp4 -a FNAME -d "Use FFmpeg to convert MKV to MP4"
set OUTNAME (string replace -i .mkv .mp4 "$FNAME")
if test "$FNAME" = "$OUTNAME";
set OUTNAME (string replace -i -- .mov .mp4 "$FNAME")
end
if test "$FNAME" = "$OUTNAME";
set OUTNAME (string replace -i -- .webm .mp4 "$FNAME")
end
if test "$FNAME" = "$OUTNAME";
set OUTNAME (string replace -i -- .mp4 -recoded.mp4 "$FNAME")
end
if test "$FNAME" = "$OUTNAME";
echo "Input must end in .mkv, .mp4, .webm, or .mov"
return 1
end
ffmpeg -i "$FNAME" -c:v h264 -crf 23 -c:a aac -b:a 192k "$OUTNAME"
or return $status
dolphin --select "$OUTNAME" & disown
end
alias l='ls -F --color=auto'
alias ll='l -lh'
alias df='df -h'
alias du='du -h'
alias grep='grep --color'
alias qtc='qtcreator -client'
alias sqlite='sqlite3'
alias docker-logfile='docker inspect --format="{{.LogPath}}"'
alias json_pp="python3 -c 'import json, sys; print(json.dumps(json.load(sys.stdin), sort_keys=True, indent=4))'"
alias trimlong="sed 's/\(.\{120\}\).*/\1…/'"
alias ffprobe-json="ffprobe -v error -hide_banner -print_format json -show_streams -show_format"
alias dot2png="dot -Tpng -O"
alias abccat="abcls -a -m -l -r -t"
alias cdp="cd (pwd -P)"
alias bcode="code $BLENDER_BUILD_ROOT/blender.code-workspace"
alias dcode="cddocs; code ."
alias wg='wget --content-disposition'
alias rbi="git rebase --interactive"
alias rbc="git rebase --continue"
alias rba="git rebase --abort"
alias gg="git gui"
alias gga="git gui citool --amend"
Git Config
My Git configuration (~/.gitconfig
) also has some nice aliases & other options:
[color]
ui = auto
[pull]
rebase = true
[push]
default = simple
[alias]
co = "checkout"
cp = "cherry-pick"
ff = "merge --ff-only"
mt = "mergetool"
up = "checkout @~1"
st = "status --ignore-submodules=none"
car = "commit --amend --reset-author"
rbi = "rebase -i"
rbc = "rebase --continue"
rba = "rebase --abort"
tpush = "!git push && git push --tags"
out = "log @{u}.. --pretty=oneline"
head = "show HEAD"
unstash = "stash pop"
authors = "!f() { git log --since 'now - 1 year' \"$@\" | grep ^Author | sed 's/Author: //' | sed 's/<.*>//' | sort -f | uniq -ci | sort -nr | nl -s '' | sort -nr; } ; f"
glog = "log --all --graph --abbrev-commit --decorate --date=short --format=format:'%C(bold blue)%h%C(reset) %C(green)(%ad)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(dim magenta)%d%C(reset)'"
onelog = "log --abbrev-commit --decorate --date=short --format=format:'%C(bold blue)%h%C(reset) %C(green)(%ad)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(dim magenta)%d%C(reset)'"
ver = "log --oneline -n 1 --no-abbrev"
[diff]
tool = kdiff3
guitool = kdiff3
[merge]
tool = kdiff3
guitool = kdiff3
renamelimit = 4096
[core]
excludesfile = /home/sybren/.configfiles/gitignore_global
[gui]
gcwarning = false
encoding = utf-8
[rerere]
enabled = true
[gc]
rerereUnresolved = 365
rerereResolved = 365