2022-10-22 17:34:02 +02:00
|
|
|
|
|
|
|
######################################################################
|
|
|
|
# ZSH aliases and helper functions for working with Git #
|
|
|
|
# #
|
|
|
|
# Licensed under MIT (C) Alicia Sykes 2022 <https://aliciasykes.com> #
|
|
|
|
######################################################################
|
2022-03-13 13:05:41 +01:00
|
|
|
|
|
|
|
# Basics
|
|
|
|
alias g="git"
|
|
|
|
alias gs="git status" # List changed files
|
|
|
|
alias ga="git add" # Add <files> to the next commit
|
|
|
|
alias gaa="git add ." # Add all changed files
|
|
|
|
alias grm="git rm" # Remove <file>
|
|
|
|
alias gc="git commit" # Commit staged files, needs -m ""
|
|
|
|
alias gps="git push" # Push local commits to <origin> <branch>
|
|
|
|
alias gpl="git pull" # Pull changes with <origin> <branch>
|
|
|
|
alias gf="git fetch" # Download branch changes, without modifying files
|
|
|
|
|
|
|
|
# Merging and Rebasing
|
|
|
|
alias grb="git rebase" # Rebase the current HEAD into <branch>
|
|
|
|
alias grba="git rebase --abort" # Cancel current rebase sesh
|
|
|
|
alias grbc="git rebase --continue" # Continue onto next diff
|
|
|
|
alias gm="git merge" # Merge <branch> into your current HEAD
|
|
|
|
|
|
|
|
# Repo setup
|
|
|
|
alias gi="git init" # Initiialize a new empty local repo
|
|
|
|
alias gcl="git clone" # Downloads repo from <url>
|
|
|
|
|
|
|
|
# Branching
|
|
|
|
alias gch="git checkout" # Switch the HEAD to <branch>
|
|
|
|
alias gb="git branch" # Create a new <branch> from HEAD
|
|
|
|
alias gd="git diff" # Show all changes to untracked files
|
2022-10-03 00:37:15 +02:00
|
|
|
alias gtree="git log --graph --oneline --decorate --abbrev-commit" # Show branch tree
|
2022-03-23 23:49:49 +01:00
|
|
|
alias gl='git log'
|
2022-03-13 13:05:41 +01:00
|
|
|
|
|
|
|
# Tags
|
|
|
|
alias gt="git tag" # Tag the current commit, 1 param
|
|
|
|
alias gtl="git tag -l" # List all tags, optionally with pattern
|
|
|
|
alias gtlm="git tag -n" # List all tags, with their messages
|
|
|
|
alias gtp="git push --tags" # Publish tags
|
|
|
|
|
|
|
|
# Origin
|
|
|
|
alias gr="git remote"
|
|
|
|
alias grs="git remote show" # Show current remote origin
|
|
|
|
alias grl="git remote -v" # List all currently configured remotes
|
|
|
|
alias grr="git remote rm origin" # Remove current origin
|
|
|
|
alias gra="git remote add" # Add new remote origin
|
|
|
|
alias grurl="git remote set-url origin" # Sets URL of existing origin
|
|
|
|
|
|
|
|
# Undoing
|
|
|
|
alias guc="git revert" # Revert a <commit>
|
|
|
|
alias gu="git reset" # Reset HEAD pointer to a <commit>, perserves changes
|
|
|
|
alias gua="git reset --hard HEAD" # Resets all uncommited changes
|
|
|
|
alias gnewmsg="git commit --amend -m" # Update <message> of previous commit
|
|
|
|
alias gclean="git clean -df" # Remove all untracked files
|
2022-03-21 22:21:54 +01:00
|
|
|
|
2022-03-23 23:49:49 +01:00
|
|
|
# Git LFS
|
|
|
|
alias glfsi='git lfs install'
|
|
|
|
alias glfst='git lfs track'
|
|
|
|
alias glfsls='git lfs ls-files'
|
|
|
|
alias glfsmi='git lfs migrate import --include='
|
|
|
|
|
|
|
|
# Push LFS changes to current branch
|
|
|
|
function gplfs() {
|
|
|
|
git lfs push origin "$(git_current_branch)" --all
|
|
|
|
}
|
|
|
|
|
2022-08-12 14:00:57 +02:00
|
|
|
alias gx='cd $(git rev-parse --show-toplevel)'
|
|
|
|
|
2022-08-16 00:26:29 +02:00
|
|
|
# Navigate back to project root (where .git is)
|
|
|
|
function jump-to-git-root {
|
|
|
|
local _root_dir="$(git rev-parse --show-toplevel 2>/dev/null)"
|
|
|
|
if [[ $? -gt 0 ]]; then
|
|
|
|
>&2 echo '\033[1;93m Not a Git repo\033[0m'
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
local _pwd=$(pwd)
|
|
|
|
if [[ $_pwd = $_root_dir ]]; then
|
|
|
|
# Handle submodules
|
|
|
|
_root_dir="$(git -C $(dirname $_pwd) rev-parse --show-toplevel 2>/dev/null)"
|
|
|
|
if [[ $? -gt 0 ]]; then
|
|
|
|
echo "\033[0;96m Already at Git repo root.\033[0m"
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
# Make `cd -` work.
|
|
|
|
OLDPWD=$_pwd
|
|
|
|
echo "\033[0;96m Git repo root: $_root_dir\033[0m"
|
|
|
|
cd $_root_dir
|
|
|
|
}
|
|
|
|
|
|
|
|
alias gj='jump-to-git-root'
|
|
|
|
|
2022-03-21 22:21:54 +01:00
|
|
|
# Shorthand clone (e.g. $ clone lissy93/dotfiles)
|
|
|
|
function clone {
|
|
|
|
default_service='github.com' # Used if full URL isn't specified
|
|
|
|
default_username='lissy93' # Used if repo org / username isn't specified
|
2023-02-11 16:53:49 +01:00
|
|
|
use_ssh=true # Use SSH instead of HTTPS
|
2022-03-21 22:21:54 +01:00
|
|
|
user_input=$1
|
|
|
|
target=${2:-''}
|
|
|
|
# Help flag passed, show manual and exit
|
|
|
|
if [[ $user_input == --help ]] || [[ $user_input == -h ]]; then
|
2023-02-11 16:53:49 +01:00
|
|
|
echo -e 'This will clone a git repo, and cd into it.';
|
|
|
|
echo -e 'Either specify repo name, oe user/repo, or a full URL.'
|
|
|
|
echo -e 'If no target directory is specified, the repo name will be used.'
|
2022-03-21 22:21:54 +01:00
|
|
|
echo -e 'E.g. `$ clone lissy93/dotfiles`'
|
|
|
|
return;
|
|
|
|
# No input specified, prompt user
|
|
|
|
elif [ $# -eq 0 ]; then
|
|
|
|
echo 'Enter a user/repo or full URL: ';
|
|
|
|
read user_input;
|
|
|
|
fi
|
|
|
|
# Determine input type, and make clone url
|
|
|
|
if [[ $user_input == git@* || $user_input == *://* ]]
|
|
|
|
then
|
|
|
|
# Full URL was provided
|
|
|
|
REPO_URL=$user_input;
|
|
|
|
elif [[ $user_input == */* ]]; then
|
|
|
|
# Username/repo was provided
|
2023-02-11 16:53:49 +01:00
|
|
|
if [ "$use_ssh" = true ] ; then
|
|
|
|
REPO_URL="git@$default_service:$user_input.git";
|
|
|
|
else
|
|
|
|
REPO_URL="https://$default_service/$user_input.git";
|
|
|
|
fi
|
2022-03-21 22:21:54 +01:00
|
|
|
else
|
|
|
|
# Just repo name was provided
|
2023-02-11 16:53:49 +01:00
|
|
|
if [ "$use_ssh" = true ] ; then
|
|
|
|
REPO_URL="git@$default_service:$default_username/$user_input.git";
|
|
|
|
else
|
|
|
|
REPO_URL="https://$default_service/$default_username/$user_input.git";
|
|
|
|
fi
|
2022-03-21 22:21:54 +01:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Clone repo
|
|
|
|
git clone $REPO_URL $target;
|
2022-11-25 00:04:56 +01:00
|
|
|
|
|
|
|
# cd into newly cloned directory
|
|
|
|
cd "$(basename "$_" .git)"
|
2023-02-11 16:53:49 +01:00
|
|
|
|
|
|
|
# Print results
|
|
|
|
if test "$?" -eq 0; then
|
|
|
|
echo -e "☑️ \033[1;96mCloned $REPO_URL into $(pwd), and cd'd into it.\033[0m"
|
|
|
|
else
|
|
|
|
echo -e "❌ \033[1;91mFailed to clone $REPO_URL\033[0m"
|
|
|
|
fi
|
2022-03-21 22:21:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
# Sync fork against upstream repo
|
|
|
|
function gsync {
|
|
|
|
# If no upstream origin provided, prompt user for it
|
|
|
|
if ! git remote -v | grep -q 'upstream'; then
|
|
|
|
echo 'Enter the upstream git url: ';
|
|
|
|
read url;
|
|
|
|
git remote add upstream "$url"
|
|
|
|
fi
|
|
|
|
git remote -v
|
|
|
|
git fetch upstream
|
|
|
|
git pull upstream master
|
|
|
|
git checkout master
|
|
|
|
git rebase upstream/master
|
|
|
|
}
|
|
|
|
|
|
|
|
# Make git commit with -m
|
|
|
|
function gcommit {
|
|
|
|
commit_msg=$@
|
|
|
|
if [ $# -eq 0 ]; then
|
|
|
|
echo 'Enter a commit message';
|
|
|
|
read commit_msg;
|
|
|
|
fi
|
|
|
|
git commit -m "$commit_msg"
|
|
|
|
}
|
|
|
|
|
|
|
|
alias gcm="gcommit"
|
|
|
|
|
|
|
|
# Fetch, rebase and push updates to current branch
|
|
|
|
# Optionally specify target, defaults to 'master'
|
|
|
|
function gfetchrebase {
|
|
|
|
if ! [ -z "$1" ]; then
|
|
|
|
branch=$1
|
|
|
|
else
|
|
|
|
branch='master'
|
|
|
|
fi
|
|
|
|
git fetch upstream
|
|
|
|
git rebase upstream/$branch
|
|
|
|
git push
|
|
|
|
}
|
|
|
|
|
|
|
|
alias gfrb="gfetchrebase"
|
|
|
|
|
2022-03-23 23:49:49 +01:00
|
|
|
# Integrates with gitignore.io to auto-populate .gitignore file
|
|
|
|
function gignore() {
|
|
|
|
curl -fLw '\n' https://www.gitignore.io/api/"${(j:,:)@}"
|
|
|
|
}
|
|
|
|
_gitignoreio_get_command_list() {
|
|
|
|
curl -sfL https://www.gitignore.io/api/list | tr "," "\n"
|
|
|
|
}
|
|
|
|
_gitignoreio () {
|
|
|
|
compset -P '*,'
|
|
|
|
compadd -S '' `_gitignoreio_get_command_list`
|
|
|
|
}
|
|
|
|
# Downloads specific git ignore template to .gitignore
|
|
|
|
gignore-apply () {
|
|
|
|
if [ -n $search_term ]; then
|
|
|
|
gignore $1 >> .gitignore
|
2022-03-21 22:21:54 +01:00
|
|
|
else
|
2022-03-23 23:49:49 +01:00
|
|
|
echo "Expected a template to be specified. Run:"
|
|
|
|
echo " $ gignore list to view all options"
|
|
|
|
echo " $ gignore [template] to preview"
|
2022-03-21 22:21:54 +01:00
|
|
|
fi
|
2022-03-22 17:29:52 +01:00
|
|
|
}
|
2022-03-21 22:21:54 +01:00
|
|
|
|
2022-03-22 17:29:52 +01:00
|
|
|
# Helper function to return URL of current repo (based on origin)
|
|
|
|
get-repo-url() {
|
|
|
|
git_base_url='https://github.com'
|
|
|
|
# Get origin from git repo + remove .git
|
|
|
|
git_url=${$(git config --get remote.origin.url)%.git}
|
|
|
|
# Process URL, and append branch / working origin
|
|
|
|
if [[ $git_url =~ ^git@ ]]; then
|
|
|
|
branch=${1:-"$(git symbolic-ref --short HEAD)"}
|
|
|
|
branchExists="$(git ls-remote --heads $git_url $branch | wc -l)"
|
|
|
|
github="$(echo $git_url | sed 's/git@//')" # Remove git@ from the start
|
|
|
|
github="$(echo $github | sed 's/\:/\//')" # Replace : with /
|
|
|
|
if [[ $branchExists == " 1" ]]; then
|
|
|
|
git_url="http://$github/tree/$branch"
|
|
|
|
else
|
|
|
|
git_url="http://$github"
|
|
|
|
fi
|
|
|
|
elif [[ $git_url =~ ^https?:// ]]; then
|
|
|
|
branch=${1:-"$(git symbolic-ref --short HEAD)"}
|
|
|
|
branchExists="$(git ls-remote --heads $git_url $branch | wc -l)"
|
|
|
|
if [[ $branchExists == " 1" ]]; then
|
|
|
|
git_url="$git_url/tree/$branch"
|
|
|
|
else
|
|
|
|
git_url="$git_url"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
# Return URL
|
|
|
|
echo $git_url
|
|
|
|
}
|
|
|
|
|
|
|
|
# Helper function that gets supported open method for system
|
|
|
|
launch-url() {
|
2022-03-21 22:21:54 +01:00
|
|
|
if hash open 2> /dev/null; then
|
|
|
|
open_command=open
|
|
|
|
elif hash xdg-open 2> /dev/null; then
|
|
|
|
open_command=xdg-open
|
|
|
|
elif hash lynx 2> /dev/null; then
|
|
|
|
open_command=lynx
|
|
|
|
else
|
|
|
|
echo -e "\033[0;33mUnable to launch browser, open manually instead"
|
2022-03-22 17:29:52 +01:00
|
|
|
echo -e "\033[1;96m🌐 URL: \033[0;96m\e[4m$1\e[0m"
|
2022-03-21 22:21:54 +01:00
|
|
|
return;
|
|
|
|
fi
|
2022-03-22 17:29:52 +01:00
|
|
|
echo $open_command
|
|
|
|
}
|
2022-03-21 22:21:54 +01:00
|
|
|
|
2022-03-22 17:29:52 +01:00
|
|
|
# Opens the current repo + branch in GitHub
|
|
|
|
open-github() {
|
|
|
|
git_base_url='https://github.com' # Modify this if using GH enterprise
|
|
|
|
if [[ ! -z $1 && ! -z $2 ]]; then
|
|
|
|
# User specified a repo
|
|
|
|
git_url=$git_base_url/$1/$2
|
|
|
|
elif git rev-parse --git-dir > /dev/null 2>&1; then
|
|
|
|
# Get URL from current repo's origin
|
|
|
|
git_url=$(get-repo-url)
|
|
|
|
else
|
|
|
|
# Not in repo, and nothing specified, open homepage
|
|
|
|
git_url=$git_base_url
|
|
|
|
fi
|
|
|
|
# Determine which open commands supported
|
|
|
|
open_command=$(launch-url $git_url)
|
2022-03-21 22:21:54 +01:00
|
|
|
# Print messages
|
|
|
|
echo -e "\033[1;96m🐙 Opening in browser: \033[0;96m\e[4m$git_url\e[0m"
|
|
|
|
# And launch!
|
|
|
|
$open_command $git_url
|
|
|
|
}
|
|
|
|
|
2022-03-22 17:29:52 +01:00
|
|
|
alias gho='open-github'
|
|
|
|
|
|
|
|
# Opens pull request tab for the current GH repo
|
|
|
|
open-github-pulls() {
|
|
|
|
# Get Repo URL
|
|
|
|
if git rev-parse --git-dir > /dev/null 2>&1; then
|
|
|
|
git_url=$(get-repo-url)
|
|
|
|
else
|
|
|
|
git_url='https://github.com'
|
|
|
|
fi
|
|
|
|
git_url="$git_url/pulls"
|
|
|
|
# Get open command
|
|
|
|
open_command=$(launch-url $git_url)
|
|
|
|
# Print message, and launch!
|
|
|
|
echo -e "\033[1;96m🐙 Opening in browser: \033[0;96m\e[4m$git_url\e[0m"
|
|
|
|
$open_command $git_url
|
|
|
|
}
|
|
|
|
|
|
|
|
alias ghp='open-github-pulls'
|
2022-08-06 21:24:34 +02:00
|
|
|
|
|
|
|
# Prompt for main SSH key passphrase, so u don't need to enter it again until session killed
|
|
|
|
alias add-key='eval "$(ssh-agent)" && ssh-add ~/.ssh/id_rsa'
|