Created
May 30, 2025 11:06
-
-
Save alvesvaren/28b89dac25628f83e481d022c4916f6c to your computer and use it in GitHub Desktop.
Revisions
-
alvesvaren created this gist
May 30, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,907 @@ #!/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