(note: surprisingly, this article was not written by Ai)
Introduction:
Git aliases are a powerful method of automating tasks - saving you time and making coding more enjoyable.
This blog post will give you everything you need to know to get started with optimizing your workflow.
Keep reading to get access to my custom code snippets that are will definitely save you many precious dev minutes and guarantee a job at google (100% guaranteed, no doubt)
Setting Up Prerequisites (2 mins)
Before diving into the aliases, here are a few prerequisites
- Ensure you have Git Bash installed. for more info see the official download page
- Ensure you have the
code
command configured (See below) - (optional) I recommend to set up git bash as default vs code terminal, for more info see setting up git bash with vs code
Setting up the code
command
The code
command creates a new file AND opens it in your code editor
~/your-project-directory/src> code my-file-name.tsx
NOTE: unlike touch
, when the new file is open in your code editor you must hit ctrl+s
to ensure is saved.
The convenience this provides is why it is beloved by many developers and a consistent part of my daily development workflow.
The code command is required for some of the advanced bash scripts later in this article to work.
Here is how to set it up:
- Inside vs-code, press F1 to open the command pallete
- type
shell command
to findShell Command: Install 'code' command in PATH command
and hit enter - restart your terminal
For more info on this, see this stack overflow post
Defining Git Bash Aliases
My approach
These scripts have been written with typescript / python developers in mind.
My aim is to create scripts that are easy to understand and change by developers most familiar with high-level programming languages.
While some members of the Bash scripting community may find my snippets somewhat unconventional, I hope that the majority finds my methods to helpful.
Defining aliases overview:
-
~/.bashrc
is where you will be placing all of your alias definitions. - You can access this using
code ~/.bashrc
(or the rc alias later on) - After making changes, ensure to save
.bashrc
restart your terminal
A few tips:
- use
ctrl+'
to open terminal in vs code - use
ctrl+shift+5
to add a new terminal- eg if you have your development sever running in one terminal, you can still use the second terminal to write commands
- use
ctrl+d
to close the specific terminal instance that you are focused on - use
ctrl+c
to cancel operation - can “restart” the terminal by using
ctrl+shift+5
to create a new one and thenctrl+d
to close the current one
Basic use cases
These basic use cases are mostly for convenience and DX
The alias for aliases!
# Overview:
# Opens ~/.bashrc in vscode so that you can edit your aliases
# Usage:
# ~/anywhere> rc
alias rc="code ~/.bashrc"
Relative navigation aliases
# Overview:
# Aliases for easily navigating relative to the current directory
# Usage:
# ~/dev/my-app/src/folder/nested-folder> ...
# ~/dev/my-app/src>
alias .='cd .' # navigate to current directory
alias ..='cd ..' # navigate to parent directory
alias ...='cd ../../' # navigate to grandparent directory
alias ....='cd ../../../' # navigate to great-grandparent directory
Package manager
# Overview:
# Runs pnpm as normal but more concise
# Replace with yarn or npm if needed
# Usage:
# ~/dev/my-app> x dev
alias x='pnpm "$@"'
Advanced custom use cases
These are custom use cases that save me a lot of time and effort everyday, and I highly recommend trying them out!
Absolute Navigation (relative to the root of the repo)
# This a helper function for the git aliases below
# credit: https://stackoverflow.com/a/38852055
# Print the name of the git working tree's root directory
function git_root() {
local root first_commit
# git displays its own error if not in a repository
root=$(git rev-parse --show-toplevel) || return
if [[ -n $root ]]; then
echo $root
return
elif [[ $(git rev-parse --is-inside-git-dir) = true ]]; then
# We're inside the .git directory
# Store the commit id of the first commit to compare later
# It's possible that $GIT_DIR points somewhere not inside the repo
first_commit=$(git rev-list --parents HEAD | tail -1) ||
echo "$0: Can't get initial commit" 2>&1 && false && return
root=$(git rev-parse --git-dir)/.. &&
# subshell so we don't change the user's working directory
( cd "$root" &&
if [[ $(git rev-list --parents HEAD | tail -1) = $first_commit ]]; then
pwd
else
echo "$FUNCNAME: git directory is not inside its repository" 2>&1
false
fi
)
else
echo "$FUNCNAME: Can't determine repository root" 2>&1
false
fi
}
# Overview:
# Custom implementation of cd command that uses absolute path from git root
# Supports custom aliases eg: r a = cd to apps
# The alises configured below are specialised for monorepo development with turbo.build
# You can easily tailor these to your needs eg for a non-monorepo setup
# Usage examples:
# ~/dev/my-app> r a
# => ~/dev/my-app/apps
#------------------------
# ~/dev/my-app> r a/w
# => ~/dev/my-app/apps/webapp
#------------------------
# ~/dev/my-app> r a/d
# => ~/dev/my-app/apps/docs
#------------------------
# ~/dev/my-app> r p
# => ~/dev/my-app/packages
#------------------------
# ~/dev/my-app> r p/ui
# => ~/dev/my-app/packages/ui
#------------------------
# ~/dev/my-app> r t
# => ~/dev/my-app/tooling
function cd_from_git_root() {
local root
local input=${1:-}
local base_key=""
local subpath=""
# if no argument provided, set default path
if [[ -z $input ]]; then
input="."
fi
# Extract base key and subpath
base_key=${input:0:1}
subpath=${input:2}
# Define key => path mappings
declare -A key_to_base_path
key_to_base_path[a]="apps"
key_to_base_path[p]="packages"
key_to_base_path[t]="tooling"
# Define specific shortcut => path mappings
declare -A shortcuts
shortcuts[a/w]="apps/webapp"
shortcuts[a/m]="apps/marketing"
shortcuts[a/d]="apps/docs"
# Check for specific shortcuts first
if [[ -n ${shortcuts[$input]} ]]; then
path="${shortcuts[$input]}"
elif [[ -n ${key_to_base_path[$base_key]} ]]; then
path="${key_to_base_path[$base_key]}/$subpath"
else
path=$input
fi
# Remove leading slash if present
path=$(echo $path | sed -r "s/^\///")
root=$(git_root) || return 1 # Get git root using custom git_root function
root="$root/$path"
cd "$root" || return 1 # Navigate to the path or return an error
}
# add convenient names
alias cdr='cd_from_git_root'
alias r='cd_from_git_root'
Scaffolding folders
# Overview:
# A custom implementation of the mkdir command that scaffolds a folder and inner files
# first argument is the folder name
# second argument is a string of options
# options:
# - s: (Story) => generate story file (folder_name.story.tsx)
# - d: (Docs) => generate docs file (folder_name.mdx)
# - r: (React) => make all generated files .tsx instead of .ts
# - t: (Test) => generate test file (folder_name.test.tsx)
# Usage examples:
# ~/dev/my-app> mkdir+ my-component rst
# creates:
# my-component
# - index.ts
# - my-component.tsx
# - my-component.story.tsx
# - my-component.test.tsx
#------------------------
# ~/dev/my-app> mkdir+ my-component s
# creates:
# my-component
# - index.ts
# - my-component.tsx
# - my-component.story.tsx
#------------------------
# ~/dev/my-app> mkdir+ my-util t
# creates:
# my-util
# - index.ts
# - my-util.tsx
# - my-util.test.tsx
#------------------------
mkdir+() {
# get values from arguments
folder_name=$1
options=$2
# Default options
declare -A opt
opt[test]="false" # Could set to true if you want to generate test files by default
opt[story]="false"
opt[docs]="false"
opt[react]="false"
# Update options based on the input string
if [[ $options == *"s"* ]]; then
opt[story]="true"
fi
if [[ $options == *"d"* ]]; then
opt[docs]="true"
fi
if [[ $options == *"r"* ]]; then
opt[react]="true"
fi
if [[ $options == *"t"* ]]; then
opt[test]="true"
fi
# Set file extension based on React option
file_extension="ts"
if [[ ${opt[react]} == "true" ]]; then
file_extension="tsx"
fi
# Create folder and base files
mkdir "$folder_name" && cd "$folder_name" &&
touch "index.${file_extension}" &&
echo "export * from './$folder_name';" >> "index.${file_extension}" &&
touch "$folder_name.${file_extension}" &&
code "$folder_name.${file_extension}"
# Generate test file by default
touch "$folder_name.test.${file_extension}"
# Generate story file if 's' is present
if [[ ${opt[story]} == "true" ]]; then
touch "$folder_name.story.${file_extension}"
fi
# Generate docs file if 'd' is present
if [[ ${opt[docs]} == "true" ]]; then
touch "$folder_name.mdx"
fi
# navigate back to where the command was run so that the user can create multiple folders
cd ..
}
Evaluation of git alias vs node.js code gen tools
Combining this approach of absolute navigation (r
alias) with the folder scaffolding alias (mkdir+
) can it super fast to build out a project. This has a significant speed advantage when compared to using node.js codegen tools like plop.js as it only uses bash and therefore can execute the commands without starting up a node.js server.
Although using plop.js is more well for usecases where you have a predictable boilerplate pattern that you reuse frequently. This is because plop enables you to more easily define the contents of the file by using the handlebars templating langauge. I do not recommend trying to define similar templates using bash.
I personally use plop for defining UI components as they all share a similar syntax for the stories / testing / definition file. Let me know if you are interested in accessing my code generation files and I may write another post to share them with you.
Conclusion:
Incorporating these Git aliases into your daily routine can significantly enhance your productivity. For further resources on coding efficiency, check out my other posts on snippets and monorepo management.
Thank you for your time and engagement. If you found this post helpful or have your own snippets to share, I’d love to hear from you in the comments.
About the author:
Thanks for reading! I’m Dawid, founder of Ream and a software engineer passionate about integrating technology with holistic personal growth. My experience in psychology, computer science, and business has fuelled my drive to create human-centric digital tools. This blog reflects my commitment to practical, efficient solutions in software engineering and beyond. If you found this post helpful or want to connect, feel free to reach out. Let’s continue to learn and grow together in our tech journeys.
Top comments (0)