Skip to content

Instantly share code, notes, and snippets.

@alvesvaren
Created May 30, 2025 11:06
Show Gist options
  • Save alvesvaren/28b89dac25628f83e481d022c4916f6c to your computer and use it in GitHub Desktop.
Save alvesvaren/28b89dac25628f83e481d022c4916f6c to your computer and use it in GitHub Desktop.
Port of most oh-my-zsh git aliases to git bash for windows
#!/bin/bash
# Git aliases and functions compatible with Git Bash on Windows
# --- Helper Functions ---
# Function to compare version numbers (requires version $1 >= version $2)
# Usage: is_at_least "2.8" "$git_version"
is_at_least() {
local required_version="$1"
local current_version="$2"
# Handle empty current_version
if [[ -z "$current_version" ]]; then
return 1 # False
fi
# Use sort -V for version comparison
# Check if current_version is >= required_version
if [[ "$(printf '%s\n' "$required_version" "$current_version" | sort -V | head -n1)" == "$required_version" ]]; then
return 0 # True (or equal)
else
return 1 # False
fi
}
# Get Git version
git_version_string=$(git version 2>/dev/null)
if [[ -n "$git_version_string" ]]; then
# Extract the version number (e.g., 2.34.1 from "git version 2.34.1.windows.1")
# Using awk for simplicity
git_version=$(echo "$git_version_string" | awk '{print $3}')
# Optional: remove suffixes like .windows.1 if needed for comparisons, though sort -V handles it often
# git_version="${git_version%%.windows.*}"
else
git_version="" # Handle case where git isn't found or fails
# echo "Warning: Could not determine git version." >&2
fi
# Get the current branch name reliably
git_current_branch() {
local branch_name
# Try symbolic-ref first, handles branches correctly
branch_name=$(git symbolic-ref --short HEAD 2>/dev/null)
local exit_code=$?
if [[ $exit_code -ne 0 ]]; then
# Fallback for detached HEAD state: show commit hash
branch_name=$(git rev-parse --short HEAD 2>/dev/null)
[[ -z "$branch_name" ]] && return 1 # Failed to get anything
fi
echo "$branch_name"
return 0
}
# --- Functions Current ---
# Back-compatibility wrapper
function current_branch() {
git_current_branch
}
# Check for develop and similarly named branches
function git_develop_branch() {
command git rev-parse --git-dir &>/dev/null || return
local branch
for branch in dev devel develop development; do
if command git show-ref -q --verify refs/heads/"$branch"; then
echo "$branch"
return 0
fi
done
echo "develop" # Default fallback name
return 1 # Indicate default was used / standard names not found
}
# Check if main exists and use instead of master
function git_main_branch() {
command git rev-parse --git-dir &>/dev/null || return
local ref
# Expands correctly in Bash
for ref in refs/{heads,remotes/{origin,upstream}}/{main,trunk,mainline,default,stable,master}; do
if command git show-ref -q --verify "$ref"; then
# Use basename for Bash equivalent of Zsh :t
echo "$(basename "$ref")"
return 0
fi
done
# If no main branch was found, fall back to master but return error
echo "master" # Default fallback name
return 1 # Indicate default was used / preferred names not found
}
function grename() {
if [[ -z "$1" || -z "$2" ]]; then
# Use function name directly in Bash
echo "Usage: grename old_branch new_branch"
return 1
fi
# Rename branch locally
git branch -m "$1" "$2"
# Rename branch in origin remote
# Suppress error if old branch didn't exist remotely
if git push origin :"${1}" &>/dev/null; then
git push --set-upstream origin "$2"
else
# Optionally inform user, but still try setting upstream for the new branch
echo "Info: Remote branch '$1' not found or couldn't be deleted." >&2
git push --set-upstream origin "$2"
fi
}
# --- Functions Work in Progress (WIP) ---
# Similar to `gunwip` but recursive "Unwips" all recent `--wip--` commits
function gunwipall() {
local _commit
_commit=$(git log --grep='--wip--' --invert-grep --max-count=1 --format=format:%H 2>/dev/null)
local current_head
current_head=$(git rev-parse HEAD 2>/dev/null)
# Check if a non-WIP commit was found and it's different from HEAD
if [[ -n "$_commit" && "$_commit" != "$current_head" ]]; then
git reset "$_commit" || return 1
elif [[ -z "$_commit" ]]; then
echo "No non-WIP commit found to reset to." >&2
return 1
fi
}
# Warn if the current branch is a WIP
function work_in_progress() {
# Use standard grep and command structure
if command git -c log.showSignature=false log -n 1 2>/dev/null | grep -q -- '--wip--'; then
echo "WIP!!"
fi
}
# --- Aliases ---
alias grt='cd "$(git rev-parse --show-toplevel || echo .)"'
# Helper function for ggpnp
_ggpnp_func() {
if [[ "$#" == 0 ]]; then
_ggl_func && _ggp_func # Assuming _ggl_func and _ggp_func are defined below
else
# Pass arguments individually using "$@"
_ggl_func "$@" && _ggp_func "$@"
fi
}
alias ggpnp='_ggpnp_func'
# No direct compdef equivalent in Bash alias files
alias ggpur='_ggu_func' # Use the helper function defined below
alias g='git'
alias ga='git add'
alias gaa='git add --all'
alias gapa='git add --patch'
alias gau='git add --update'
alias gav='git add --verbose'
# Ensure deleted files are handled robustly
alias gwip='git add -A && git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"'
alias gam='git am'
alias gama='git am --abort'
alias gamc='git am --continue'
alias gamscp='git am --show-current-patch'
alias gams='git am --skip'
alias gap='git apply'
alias gapt='git apply --3way'
alias gbs='git bisect'
alias gbsb='git bisect bad'
alias gbsg='git bisect good'
alias gbsn='git bisect new' # Assuming 'new' is valid; 'start' is common
alias gbso='git bisect old' # Assuming 'old' is valid; 'bad'/'good' are common
alias gbsr='git bisect reset'
alias gbss='git bisect start'
alias gbl='git blame -w'
alias gb='git branch'
alias gba='git branch --all'
alias gbd='git branch --delete'
alias gbD='git branch --delete --force'
# Helper function for gbda
_gbda_func() {
local main_branch develop_branch branches_to_delete
main_branch=$(git_main_branch) || main_branch="master" # Fallback if function fails
develop_branch=$(git_develop_branch) || develop_branch="develop" # Fallback if function fails
# Escape branches for the regex
local safe_main=$(printf '%s\n' "$main_branch" | sed 's/[^^]/[&]/g; s/\^/\\^/g')
local safe_develop=$(printf '%s\n' "$develop_branch" | sed 's/[^^]/[&]/g; s/\^/\\^/g')
# Get merged branches excluding main/develop and the current branch (*)
branches_to_delete=$(git branch --no-color --merged | command grep -vE "^\*|^\s*($safe_main|$safe_develop)\s*$" | sed 's/^\s*//') # Trim whitespace
if [[ -n "$branches_to_delete" ]]; then
# Use xargs safely with null delimiter if possible (requires GNU xargs/findutils)
# Otherwise, process line by line for safety with spaces/special chars
echo "$branches_to_delete" | while IFS= read -r branch; do
# Double check it's not main/develop again, just in case
if [[ "$branch" != "$main_branch" && "$branch" != "$develop_branch" ]]; then
git branch --delete "$branch"
fi
done
else
echo "No merged branches (excluding ${main_branch}, ${develop_branch}, and current) to delete."
fi
}
alias gbda='_gbda_func'
# Helper function for gbds (Delete Squashed)
_gbds_func() {
local default_branch main_branch_status
default_branch=$(git_main_branch)
main_branch_status=$?
if [[ $main_branch_status -ne 0 ]]; then
default_branch=$(git_develop_branch)
if [[ $? -ne 0 ]]; then
echo "Warning: Could not determine main or develop branch for comparison. Using 'master' as fallback." >&2
default_branch="master" # Or choose another default or error out
fi
fi
if [[ -z "$default_branch" ]]; then
echo "Error: Could not determine a default branch to compare against." >&2
return 1
fi
git for-each-ref refs/heads/ --format='%(refname:short)' | while read branch; do
# Skip the default branch itself
if [[ "$branch" == "$default_branch" ]]; then
continue
fi
local merge_base
merge_base=$(git merge-base "$default_branch" "$branch" 2>/dev/null)
if [[ -z "$merge_base" ]]; then
# echo "Info: Cannot find merge base between $default_branch and $branch. Skipping." >&2
continue
fi
# Check if the branch tip is reachable from default_branch (already merged)
if git merge-base --is-ancestor "$branch" "$default_branch"; then
# echo "Info: Branch '$branch' seems merged into '$default_branch'. Consider 'gbda'." >&2
continue # Already merged, gbda handles this
fi
# Create a temporary commit to check with git cherry
# This checks if the *changes* introduced by the branch relative to its merge-base
# are already present in the default branch (e.g., due to squash merge or cherry-pick)
local branch_tree branch_commit temp_commit
branch_commit=$(git rev-parse "$branch" 2>/dev/null)
branch_tree=$(git rev-parse "$branch^{tree}" 2>/dev/null)
if [[ -z "$branch_commit" || -z "$branch_tree" ]]; then
echo "Warning: Could not parse branch '$branch'. Skipping." >&2
continue
fi
# Create a commit object in memory representing the branch's state based on merge-base
# The message "_" is arbitrary
temp_commit=$(git commit-tree "$branch_tree" -p "$merge_base" -m "_" 2>/dev/null)
if [[ -z "$temp_commit" ]]; then
echo "Warning: Could not create temporary commit for branch '$branch'. Skipping." >&2
continue
fi
# Use git cherry to find commits in temp_commit not equivalent in default_branch
# If 'git cherry' output starts with '-', it means the commit is equivalent (present)
# If output starts with '+', it means the commit is not equivalent (not present)
local cherry_output
cherry_output=$(git cherry -v "$default_branch" "$temp_commit" 2>/dev/null)
# Check if cherry output indicates the commit *is* present (starts with '-')
# We check if the output is *not* empty AND *does not* start with '+'
# This implies it starts with '-' or is empty (error?), meaning changes are likely present.
# A safer check might be specifically for '-'.
if [[ "$cherry_output" == -* ]]; then
echo "Branch '$branch' changes appear to be present in '$default_branch' (squashed/cherry-picked?). Deleting with -D."
git branch -D "$branch"
# else
# echo "Branch '$branch' has unique changes compared to '$default_branch'."
fi
done
}
alias gbds='_gbds_func'
# Use standard quoting for awk
alias gbgd='LANG=C git branch --no-color -vv | grep ": gone]" | cut -c 3- | awk '\''{print $1}'\'' | xargs -r git branch -d' # Added -r to xargs
alias gbgD='LANG=C git branch --no-color -vv | grep ": gone]" | cut -c 3- | awk '\''{print $1}'\'' | xargs -r git branch -D' # Added -r to xargs
alias gbm='git branch --move'
alias gbnm='git branch --no-merged'
alias gbr='git branch --remote'
# Helper for ggsup
_ggsup_func() {
local current_b
current_b=$(git_current_branch)
if [[ -n "$current_b" ]]; then
git branch --set-upstream-to="origin/${current_b}"
else
echo "Error: Could not determine current branch." >&2
return 1
fi
}
alias ggsup='_ggsup_func'
alias gbg='LANG=C git branch -vv | grep ": gone]"' # Shows branches whose upstream is gone
alias gco='git checkout'
alias gcor='git checkout --recurse-submodules'
alias gcb='git checkout -b'
alias gcB='git checkout -B'
# Helper for gcd
_gcd_func() {
local target_branch
target_branch=$(git_develop_branch) # Gets the name, status indicates if default was used
git checkout "$target_branch"
}
alias gcd='_gcd_func'
# Helper for gcm
_gcm_func() {
local target_branch
target_branch=$(git_main_branch) # Gets the name, status indicates if default was used
git checkout "$target_branch"
}
alias gcm='_gcm_func'
alias gcp='git cherry-pick'
alias gcpa='git cherry-pick --abort'
alias gcpc='git cherry-pick --continue'
alias gclean='git clean --interactive -d'
alias gcl='git clone --recurse-submodules'
# Filter options might depend on Git version, but generally compatible
alias gclf='git clone --recursive --shallow-submodules --filter=blob:none --also-filter-submodules'
# Helper function for gccd (clone and cd)
gccd() {
local last_arg target_dir repo_url clone_dir
# Store the last argument before git clone runs
# Bash doesn't have a simple equivalent for Zsh's $_ behavior related to command output directories
# We'll rely on the standard git clone behavior
# If the last arg looks like a directory target, save it
if [[ "$#" -gt 0 && ! "${@: -1}" =~ ^(git@|https?://|ssh://|ftps?://) ]]; then
clone_dir="${@: -1}"
fi
command git clone --recurse-submodules "$@" || return $?
# Now determine where git cloned it
if [[ -n "$clone_dir" && -d "$clone_dir" ]]; then
# If an explicit directory was given and exists now, use it
target_dir="$clone_dir"
else
# Otherwise, infer from the last argument that was likely the URL
repo_url="${@: -1}" # Simplistic assumption: last arg was URL
# Derive directory name from URL: basename, remove .git suffix
target_dir=$(basename "$repo_url" .git)
fi
# Check if the determined directory exists and cd into it
if [[ -d "$target_dir" ]]; then
cd "$target_dir" || { echo "Error: Failed to cd into '$target_dir'" >&2; return 1; }
echo "Cloned and changed directory to '$target_dir'"
else
echo "Warning: Cloned repository, but could not determine target directory '$target_dir' to cd into." >&2
# Stay in the current directory
fi
}
# No compdef equivalent
alias gcam='git commit --all --message'
alias gcas='git commit --all --signoff'
alias gcasm='git commit --all --signoff --message'
alias gcs='git commit --gpg-sign'
alias gcss='git commit --gpg-sign --signoff'
alias gcssm='git commit --gpg-sign --signoff --message'
alias gcmsg='git commit --message'
alias gcsm='git commit --signoff --message'
alias gc='git commit --verbose'
alias gca='git commit --verbose --all'
alias gca!='git commit --verbose --all --amend'
alias gcan!='git commit --verbose --all --no-edit --amend'
alias gcans!='git commit --verbose --all --signoff --no-edit --amend'
alias gcann!='git commit --verbose --all --date=now --no-edit --amend' # Check if --date=now works as expected
alias gc!='git commit --verbose --amend'
alias gcn='git commit --verbose --no-edit' # Assumes you want --no-edit always
alias gcn!='git commit --verbose --no-edit --amend'
alias gcf='git config --list'
alias gdct='git describe --tags $(git rev-list --tags --max-count=1)'
alias gd='git diff'
alias gdca='git diff --cached'
alias gdcw='git diff --cached --word-diff'
alias gds='git diff --staged' # Same as gdca
alias gdw='git diff --word-diff'
# Helper for gdv (diff with view - needs 'view' or adjust editor)
_gdv_func() {
# On Windows 'view' might not exist. 'less' is common in Git Bash.
# Or use default $GIT_EDITOR / $EDITOR / vi
local editor=${GIT_PAGER:-${GIT_EDITOR:-${EDITOR:-less}}} # Prioritize pager, then editors, fallback less
git diff -w "$@" | "$editor"
}
alias gdv='_gdv_func'
# No compdef equivalent
alias gdup='git diff @{upstream}'
# Helper function for gdnolock (diff exclude lock files)
_gdnolock_func() {
# Bash doesn't have the :(exclude) syntax directly in arguments like Zsh
# Use pathspecs passed to git diff
git diff "$@" -- . ":(exclude)package-lock.json" ":(exclude)*.lock"
}
alias gdnolock='_gdnolock_func'
# No compdef equivalent
alias gdt='git diff-tree --no-commit-id --name-only -r'
alias gf='git fetch'
# Conditional alias for gfa based on Git version
if is_at_least "2.8" "$git_version"; then
alias gfa='git fetch --all --tags --prune --jobs=10'
else
alias gfa='git fetch --all --tags --prune'
fi
alias gfo='git fetch origin'
alias gg='git gui citool &' # Use & for background
alias gga='git gui citool --amend &' # Use & for background
alias ghh='git help'
alias glgg='git log --graph'
alias glgga='git log --graph --decorate --all'
alias glgm='git log --graph --max-count=10'
# Use printf for colors in log formats if needed, though Git often handles auto color
# Assuming terminal supports colors, Git's %C(...) usually works in Git Bash
alias glods='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset" --date=short'
alias glod='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset"'
alias glola='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --all'
alias glols='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --stat'
alias glol='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"'
alias glo='git log --oneline --decorate'
alias glog='git log --oneline --decorate --graph'
alias gloga='git log --oneline --decorate --graph --all'
# Pretty log messages helper function
_git_log_prettily() {
if [[ -n "$1" ]]; then
git log --pretty="$1"
else
# Optional: Provide default log or usage message
git log --oneline --decorate --graph --max-count=20
# echo "Usage: glp <format_string>" >&2
# return 1
fi
}
alias glp='_git_log_prettily'
# No compdef equivalent
alias glg='git log --stat'
alias glgp='git log --stat --patch'
# grep syntax is compatible
alias gignored='git ls-files -v | grep "^[[:lower:]]"'
alias gfg='git ls-files | grep'
alias gm='git merge'
alias gma='git merge --abort'
alias gmc='git merge --continue'
alias gms='git merge --squash'
alias gmff='git merge --ff-only'
# Helper for gmom
_gmom_func() {
local target_branch
target_branch=$(git_main_branch) # Gets name, status ignored here
git merge "origin/${target_branch}"
}
alias gmom='_gmom_func'
# Helper for gmum
_gmum_func() {
local target_branch
target_branch=$(git_main_branch) # Gets name, status ignored here
git merge "upstream/${target_branch}"
}
alias gmum='_gmum_func'
alias gmtl='git mergetool --no-prompt'
alias gmtlvim='git mergetool --no-prompt --tool=vimdiff'
alias gl='git pull'
alias gpr='git pull --rebase'
alias gprv='git pull --rebase -v'
alias gpra='git pull --rebase --autostash'
alias gprav='git pull --rebase --autostash -v'
# Helper function for ggu (pull --rebase current or specified)
_ggu_func() {
local b
if [[ "$#" -eq 0 ]]; then
b=$(git_current_branch)
if [[ -z "$b" ]]; then echo "Error: No current branch found." >&2; return 1; fi
command git pull --rebase origin "$b"
elif [[ "$#" -eq 1 ]]; then
command git pull --rebase origin "$1"
else
echo "Usage: ggu [branch_name]" >&2
return 1
fi
}
alias ggu='_ggu_func'
# No compdef equivalent
# Helper for gprom
_gprom_func() {
local target_branch
target_branch=$(git_main_branch)
git pull --rebase origin "$target_branch"
}
alias gprom='_gprom_func'
# Helper for gpromi
_gpromi_func() {
local target_branch
target_branch=$(git_main_branch)
git pull --rebase=interactive origin "$target_branch"
}
alias gpromi='_gpromi_func'
# Helper for gprum
_gprum_func() {
local target_branch
target_branch=$(git_main_branch)
git pull --rebase upstream "$target_branch"
}
alias gprum='_gprum_func'
# Helper for gprumi
_gprumi_func() {
local target_branch
target_branch=$(git_main_branch)
git pull --rebase=interactive upstream "$target_branch"
}
alias gprumi='_gprumi_func'
# Helper function for ggpull (pull current branch from origin)
_ggpull_func() {
local current_b
current_b=$(git_current_branch)
if [[ -n "$current_b" ]]; then
git pull origin "$current_b"
else
echo "Error: Could not determine current branch." >&2
return 1
fi
}
alias ggpull='_ggpull_func'
# Helper function for ggl (pull origin current or specified)
_ggl_func() {
local b
if [[ "$#" -eq 0 ]]; then
b=$(git_current_branch)
if [[ -z "$b" ]]; then echo "Error: No current branch found." >&2; return 1; fi
command git pull origin "$b"
else
# Pass all arguments using "$@" (handles spaces in names if they occur)
command git pull origin "$@"
fi
}
alias ggl='_ggl_func'
# No compdef equivalent
# Helper for gluc
_gluc_func() {
local current_b
current_b=$(git_current_branch)
if [[ -n "$current_b" ]]; then
git pull upstream "$current_b"
else
echo "Error: Could not determine current branch." >&2
return 1
fi
}
alias gluc='_gluc_func'
# Helper for glum
_glum_func() {
local target_branch
target_branch=$(git_main_branch)
git pull upstream "$target_branch"
}
alias glum='_glum_func'
alias gp='git push'
alias gpd='git push --dry-run'
# Helper function for ggf (force push origin current or specified)
_ggf_func() {
local b
if [[ "$#" -eq 0 ]]; then
b=$(git_current_branch)
if [[ -z "$b" ]]; then echo "Error: No current branch found." >&2; return 1; fi
command git push --force origin "$b"
elif [[ "$#" -eq 1 ]]; then
command git push --force origin "$1"
else
echo "Usage: ggf [branch_name]" >&2
return 1
fi
}
alias ggf='_ggf_func'
# No compdef equivalent
alias gpf!='git push --force'
# Conditional alias for gpf (force with lease)
if is_at_least "2.30" "$git_version"; then
alias gpf='git push --force-with-lease --force-if-includes'
else
alias gpf='git push --force-with-lease'
fi
# Helper function for ggfl (force-with-lease push origin current or specified)
_ggfl_func() {
local b push_command
# Determine the correct force-with-lease command based on version
if is_at_least "2.30" "$git_version"; then
push_command=(git push --force-with-lease --force-if-includes origin)
else
push_command=(git push --force-with-lease origin)
fi
if [[ "$#" -eq 0 ]]; then
b=$(git_current_branch)
if [[ -z "$b" ]]; then echo "Error: No current branch found." >&2; return 1; fi
"${push_command[@]}" "$b"
elif [[ "$#" -eq 1 ]]; then
"${push_command[@]}" "$1"
else
echo "Usage: ggfl [branch_name]" >&2
return 1
fi
}
alias ggfl='_ggfl_func'
# No compdef equivalent
# Helper function for gpsup (push set upstream)
_gpsup_func() {
local current_b
current_b=$(git_current_branch)
if [[ -n "$current_b" ]]; then
git push --set-upstream origin "$current_b"
else
echo "Error: Could not determine current branch." >&2
return 1
fi
}
alias gpsup='_gpsup_func'
# Helper function for gpsupf (push set upstream force-with-lease)
_gpsupf_func() {
local current_b push_command base_command
current_b=$(git_current_branch)
if [[ -z "$current_b" ]]; then
echo "Error: Could not determine current branch." >&2
return 1
fi
base_command=(git push --set-upstream origin "$current_b")
if is_at_least "2.30" "$git_version"; then
push_command=("${base_command[@]}" --force-with-lease --force-if-includes)
else
push_command=("${base_command[@]}" --force-with-lease)
fi
"${push_command[@]}"
}
alias gpsupf='_gpsupf_func'
alias gpv='git push --verbose'
alias gpoat='git push origin --all && git push origin --tags'
alias gpod='git push origin --delete'
# Helper function for ggpush (push current branch to origin)
_ggpush_func() {
local current_b
current_b=$(git_current_branch)
if [[ -n "$current_b" ]]; then
git push origin "$current_b"
else
echo "Error: Could not determine current branch." >&2
return 1
fi
}
alias ggpush='_ggpush_func'
# Helper function for ggp (push origin current or specified)
_ggp_func() {
local b
if [[ "$#" -eq 0 ]]; then
b=$(git_current_branch)
if [[ -z "$b" ]]; then echo "Error: No current branch found." >&2; return 1; fi
command git push origin "$b"
else
# Pass all arguments using "$@"
command git push origin "$@"
fi
}
alias ggp='_ggp_func'
# No compdef equivalent
alias gpu='git push upstream'
alias grb='git rebase'
alias grba='git rebase --abort'
alias grbc='git rebase --continue'
alias grbi='git rebase --interactive'
alias grbo='git rebase --onto'
alias grbs='git rebase --skip'
# Helper for grbd
_grbd_func() {
local target_branch
target_branch=$(git_develop_branch)
git rebase "$target_branch"
}
alias grbd='_grbd_func'
# Helper for grbm
_grbm_func() {
local target_branch
target_branch=$(git_main_branch)
git rebase "$target_branch"
}
alias grbm='_grbm_func'
# Helper for grbom
_grbom_func() {
local target_branch
target_branch=$(git_main_branch)
git rebase "origin/${target_branch}"
}
alias grbom='_grbom_func'
# Helper for grbum
_grbum_func() {
local target_branch
target_branch=$(git_main_branch)
git rebase "upstream/${target_branch}"
}
alias grbum='_grbum_func'
alias grf='git reflog'
alias gr='git remote'
alias grv='git remote --verbose'
alias gra='git remote add'
alias grrm='git remote remove'
alias grmv='git remote rename'
alias grset='git remote set-url'
alias grup='git remote update'
alias grh='git reset'
alias gru='git reset --' # Use '--' to separate paths from revisions if needed
alias grhh='git reset --hard'
alias grhk='git reset --keep'
alias grhs='git reset --soft'
alias gpristine='git reset --hard && git clean --force -dfx'
alias gwipe='git reset --hard && git clean --force -df' # Slightly safer than -dfx
# Helper for groh
_groh_func() {
local current_b
current_b=$(git_current_branch)
if [[ -n "$current_b" ]]; then
git reset "origin/${current_b}" --hard
else
echo "Error: Could not determine current branch." >&2
return 1
fi
}
alias groh='_groh_func'
alias grs='git restore'
alias grss='git restore --source'
alias grst='git restore --staged'
alias gunwip='last_msg=$(git log -1 --pretty=%s); if [[ "$last_msg" == *"--wip--"* ]]; then git reset HEAD~1; else echo "Last commit is not a WIP commit."; fi'
alias grev='git revert'
alias greva='git revert --abort'
alias grevc='git revert --continue'
alias grm='git rm'
alias grmc='git rm --cached'
alias gcount='git shortlog --summary --numbered'
alias gsh='git show'
alias gsps='git show --pretty=short --show-signature'
alias gstall='git stash --all'
alias gstaa='git stash apply'
alias gstc='git stash clear'
alias gstd='git stash drop'
alias gstl='git stash list'
alias gstp='git stash pop'
# Conditional alias for gsta (stash push/save)
if is_at_least "2.13" "$git_version"; then
alias gsta='git stash push'
else
alias gsta='git stash save'
fi
alias gsts='git stash show --patch'
alias gst='git status'
alias gss='git status --short'
alias gsb='git status --short --branch'
alias gsi='git submodule init'
alias gsu='git submodule update'
alias gsd='git svn dcommit'
# Helper for git-svn-dcommit-push
_git_svn_dcommit_push_func() {
local target_branch
target_branch=$(git_main_branch)
# Assuming 'github' is the correct remote name for the Git repo mirror
git svn dcommit && git push github "${target_branch}:svntrunk"
}
alias git-svn-dcommit-push='_git_svn_dcommit_push_func'
alias gsr='git svn rebase'
alias gsw='git switch'
alias gswc='git switch --create'
# Helper for gswd
_gswd_func() {
local target_branch
target_branch=$(git_develop_branch)
git switch "$target_branch"
}
alias gswd='_gswd_func'
# Helper for gswm
_gswm_func() {
local target_branch
target_branch=$(git_main_branch)
git switch "$target_branch"
}
alias gswm='_gswm_func'
alias gta='git tag --annotate'
alias gts='git tag --sign'
alias gtv='git tag | sort -V' # Assumes standard sort, Git Bash usually has GNU sort
alias gignore='git update-index --assume-unchanged'
alias gunignore='git update-index --no-assume-unchanged'
alias gwch='git whatchanged -p --abbrev-commit --pretty=medium'
alias gwt='git worktree'
alias gwta='git worktree add'
alias gwtls='git worktree list'
alias gwtmv='git worktree move'
alias gwtrm='git worktree remove'
alias gstu='gsta --include-untracked' # Relies on gsta alias defined above
# Helper function for gtl (list tags matching prefix)
_gtl_func() {
# Bash doesn't need noglob here. Ensure $1 is quoted.
git tag --sort=-v:refname -n --list "${1}*"
}
alias gtl='_gtl_func'
# Use `command` prefix and `&` for background in Bash
alias gk='command gitk --all --branches &'
alias gke='command gitk --all $(git log --walk-reflogs --pretty=%h) &'
# --- Deprecated Alias Handling ---
# Define functions for old aliases that show a warning and call the new one
# ANSI color codes: Yellow=\033[0;33m, Red=\033[0;31m, Green=\033[0;32m, Reset=\033[0m
deprecated_map=(
"gup:gpr"
"gupv:gprv"
"gupa:gpra"
"gupav:gprav"
"gupom:_gprom_func" # Call helper func directly if new alias uses one
"gupomi:_gpromi_func" # Call helper func directly
)
item="" old_alias="" new_alias_cmd=""
for item in "${deprecated_map[@]}"; do
old_alias="${item%%:*}" # Part before :
new_alias_cmd="${item#*:}" # Part after :
# Use eval to dynamically create a function named $old_alias
# This function prints a warning and executes the new command, passing arguments
eval "
${old_alias}() {
printf \"\\033[0;33m[Git Alias] Warning: '%s' is deprecated, using '%s' instead.\\033[0m\\n\" \"${old_alias}\" \"${new_alias_cmd}\" >&2
\"${new_alias_cmd}\" \"\$@\" # Execute the new command/function with original arguments
}
"
done
unset item old_alias new_alias_cmd deprecated_map # Clean up loop variables
# --- Cleanup ---
unset git_version_string git_version # Clean up global version variable
# --- End of Script ---
# To use these aliases, source this file in your ~/.bashrc or ~/.bash_profile:
# source /path/to/this/script.sh
@alvesvaren
Copy link
Author

alvesvaren commented May 30, 2025

What is this?

This is a file with most aliases from oh-my-zsh to make using git easier from the terminal.

The script is made for git bash on windows, but it might work fine in normal bash too, although there I'd just use zsh instead.

It doesn't do tab completions for most commands, but otherwise it should behave the same as in zsh

To install

  1. Make sure git bash is installed
  2. Add source ~/.git-aliases.sh anywhere in your ~/.bashrc

Note: Not all commands have been tested, so if you find any bugs, please add them to the comments here!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment