November 12, 2025 at 06:34 PM EST
Migrating shell and git notes
November 12, 2025 at 06:34 PM EST
Migrating shell and git notes
Default to shortcuts and be patient with the documentation.
Directory: file that contains pointers (inodes) to other files.
Variables
#${} is useful for adding more characters
name="Joe"; echo ${name} ; echo $name ; echo ${name}_rocks.
Double quotes("") preserve the content as stored in the variable. Otherwise, it’s processed by the shell.
Arrays:
# In zsh, arrays are 1-indexed
# No commas
words=("Joe" "needs" "to" "breathe")
echo ${words[1]} # Joe
echo ${words[@]} # Joe needs to breathe
echo ${#words[@]} # 4
Conditionals and conditional expressions
# Watch your spaces a
# Double brackets support more operations
# Brackets variations: [[ exp ]], [exp]
# Expressions: -d -a ( exp ), -eq, -ne.
if [ 10 -eq 10 ]; then
echo "makes sense"
else
echo "no"
fi
Refer to bracket differences and conditional expressions
Loops
# while
i=0
count=0
while [[ $i -lt 10 ]]; do
# (()) is for arithmetic expressions
(( count++ ))
(( i++ ))
done
echo "Count: ${count}"
# for
items=("Take" "it" "easy")
for item in $items; do
echo $item
done
Refer to loops
man
man command
du
Let’s man du 1. and decypher the synopsis:
du [-Aclnx] [-H | -L | -P] [-g | -h | -k | -m] [-a | -s | -d depth]
find
The find command took time to understand. I had to understand what primaries exactly meant, but it turns out they’re expressions specific to the find command. An expression is a combination (primaries in this example) of expressions and operators that evaluate to true or false.
find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
sh
Allows to run a mini-shell script to run more complex commands. It’s useful to create git aliases or embellish certain commands.
sh -c [-abCefhimnuvx] [-o option]… [+abCefhimnuvx] [+o option]… command_string
What do these commands do?
# You can also write it like: du -h -d -1
du -hd1 | sort -n
Sort the file sizes at depth 1 (immediate subdirectories). | is passing the input from one command to the other.
# -type, -name -exec are all primaries
find . -type d -name '202*' -exec rm -r {} \;
Find all the directories with 202* and remove them.
find . -type f \( -name "*.aif" -o -name "*.wav" \) -exec mv {} . \;
Move .aif and .wav files to the current directory
find . -type d -exec sh -c 'echo "Found {}"' \;
Find all the directories and echo their result.
mv *svg* SVG/
Move any file containing svg to the SVG/ folder
Aliases saves some time to open and boot up projects. These are some of mine:
alias py=/usr/bin/python3
alias refresh='source ~/.zshrc'
alias editshell='vi ~/.zshrc'
alias editgit='vi ~/.gitconfig'
alias nrb='npm run backend'
alias nrd='npm run dev'
alias guitar='cd /Users/kanleafsnail/Desktop/Through/Projects/Python\ Projects/tkinter_music_theory && source .venv/bin/activate && python3 -m package.gui.guitar_gui'
alias diarydb='cd /Users/kanleafsnail/Desktop/Through/Projects/React\ Projects/Diary/diary/backend/instance && sqlite3 diary .db'
alias ios='open /Users/kanleafsnail/Desktop/Through/Projects/iOS\ Projects/'
alias joe='cd /Users/joesnail/Through/Projects/joefarah/joe-farah && nrd'
The terminal is my motivational speaker.
quotes=(
"Be more patient when you're looking at documentation, it will save hours."
"Every line is susceptible to ERROR."
"How do I even start to think about this?"
"The hidden secrets of the problem: What can I use?"
"Do I really know what this function is doing?"
"What's the initial configuration of my problem?"
"Do I need more variables, do I need less variables?"
"Is my order correct?"
"Are you going too fast?"
"Is it a logical error, a language error?"
"Say the English before you say the code"
"Relax through the edge cases"
"Sometimes, your initial approach is just plain wrong. Nothing wrong with that. It's just learning."
)
# @: special parameter to access all elements
for q in ${quotes[@]}; do
echo ${q}
done
# RANDOM's range is 0 - 32767,
# zsh arrays are 1-indexed: add + 1.
echo ${quotes[RANDOM % ${#quotes[@]} + 1]}
Counting items in subdirectories
count_items_in_directory() {
# Prompt user for directory path
# zsh style read
read "dir_path?Enter the directory path: "
# Check if the directory exists
if [ -d "$dir_path" ]; then
# List directories under the specified directory with item counts
find "$dir_path" -mindepth 1 -maxdepth 1 -type d -exec sh -c 'echo "{}: " && find "{}" -mindepth 1 | wc -l' \;
else
echo "Directory '$dir_path' does not exist."
fi
}
Modulo practice
practice_mod() {
while true; do
# RANDOM % N: [0, n-1]
a=$(( RANDOM % 41 - 20 ))
b=$(( RANDOM % 21 - 10 ))
[[ $b -eq 0 ]] && b=1
read "answer?What is ${a} mod ${b}? "
[[ ${answer} == "exit" ]] && break
result=$(( a % b ))
[[ ${answer} -eq ${result} ]] && echo "Correct!" || echo "Wrong: ${result}"
done
}
Creating an .env file with the test command. Use the backslash.
# package.json from Gameok
# Note: echo \" \" and \\n
"create-env": "cd backend && test -f .env || echo \"SECRET_KEY= #fill\\nADMIN=#fill\\nEMAIL=#fill\\nPASSWORD= #fill\\nDATABASE_URL=sqlite:///gamelibrary.db\\nDATABASE_TRACKING=False\\nFLASK_APP=gameok.py\\nFLASK_ENV=development\\nFLASK_DEBUG=1\" > .env"
Help
git command --help
Navigation
^(#): parent # merge commits
~: n commits behind # simply go behind
^..: # range
c1^..cn # c1 excluded, cn included.
^2~3 # 2nd parent, go 3 commits behind
Branch Management
git branch -m old new # Rename branch
git branch -d branch-name # Checkout the branch first
git checkout -b new-branch # Create a new branch and move to it
git branch -f main HEAD~3 # Moving a branch pointer
Reset
git reset --soft HEAD~ # undo commit but keep changes staged
git reset --mixed HEAD~ # undo commit and unstage
git reset --hard HEAD~ # working directory changes to the latest commit
Animations: Reset
Merge
# You're on the branch you want feature to be merged with.
git merge feature
Animations: Merge, Conflict, Pull
Rebase
The first argument is always what you’re rebasing to.
# implicit: If I am on branch X
git rebase main
# explicit: I could be anywhere
git rebase main A
Cherry-pick
Plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn’t an ancestor of HEAD).
# Simplest pattern
git cherry-pick commit
Reflog
# Shows where all your head were pointing in the past.
git reflog
# HEAD@{#} <-- number of moves ago
# 144d2b2 HEAD@{1}: commit: Add post 12
# 9fdfd49 HEAD@{2}: commit: Add post 11
Show
# git show [<options>] [<object>…]
# --pretty and --name-only are options
# <object> here is omitted: the current commit
git show --pretty="" --name-only # no headers shown
Diff
git diff --pretty="" --name-only 370c264 144d2b2
Remote
git remote add origin url # Add remote
git remote -v # Show remote
Revert: creates a new commit that reverse the changes of that commit
git revert commit
Creating custom aliases for git.
# shell alias
alias editgit='vi ~/.gitconfig'
# Applies to my system account (whoami)
git config --global --get-regexp alias
# You can have specific configuration for certain projects.
.git/config
# git + alias
# !: treats it as a shell command
[alias]
st= status
#cm: see net block
cm-no-edit= !git add . && git commit --amend --no-edit
ptr= push origin main
f-ptr= push --force origin main
tree= log --all --graph --decorate --oneline
Fast way to commit
# Without zsh: you do: read -p
cm= !zsh -c 'read \"msg?Enter a commit message: \" && git add . && git commit -m ${msg}'
Rebasing and squashing
git rebase -i HEAD~# # of commits
# interactive menu: squash
git rebase --continue
Squash all commits
# rev-list gives you the commits reachable from where you specify
# $() for shell command
# commit with 0 parent: first one.
git reset --soft $(git rev-list --max-parents=0 HEAD)
git commit -m "What did you do!"
View repository size
# v: verbose H: human-readable
git count-objects -vH
Removing large files from a git history with git-filter-repo
git filter-repo --path large-file.zip --invert-paths --all
# Accidentally commited large videos
git filter-repo --path videos.mp4 --invert-paths
Untrack a specific file
git ls-files
git rm --cached filename
Shell
Vim
Mac
Git
No comments on this post yet. Be the first to share your wisdom :).