Skip to content

Instantly share code, notes, and snippets.

@huaminghuangtw
Last active March 10, 2024 16:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huaminghuangtw/24b029222e1152ca34138521907c15e3 to your computer and use it in GitHub Desktop.
Save huaminghuangtw/24b029222e1152ca34138521907c15e3 to your computer and use it in GitHub Desktop.
My Git Configuration
[user]
name = Hua-Ming Huang
email = huaming.huang.tw@gmai.com
[github]
user = huaminghuangtw
tokentype = ssh
[include]
path = ~/.git-sendemail
[help]
autocorrect = 1
[init]
defaultBranch = main
[push]
default = current
[pull]
default = current
rebase = true
[diff]
mnemonicprefix = true
ignoreSubmodules = dirty
[branch]
autosetuprebase = always
[apply]
# Detect whitespace errors when applying a patch
whitespace = fix
[url "https://github"]
insteadOf = git://github
[url "git@github.com:github"]
insteadOf = "https://github.com/github"
insteadOf = "github:github"
insteadOf = "git://github.com/github"
[url "git@github.com:"]
pushInsteadOf = "https://github.com/"
pushInsteadOf = "github:"
pushInsteadOf = "git://github.com/"
[url "git://github.com/"]
insteadOf = "github:"
[url "git@gist.github.com:"]
insteadOf = "gst:"
pushInsteadOf = "gist:"
pushInsteadOf = "git://gist.github.com/"
[url "git://gist.github.com/"]
insteadOf = "gist:"
[submodule]
recurse = true
[color]
ui = true
branch = auto
diff = auto
status = auto
[alias]
# See more examples in https://github.com/GitAlias/gitalias/blob/main/gitalias.txt
# Note: using the "!" prefix allows one to use any command and not just git commands in the alias
# Note: $@ means all command line parameters passed
# TODO: done, interactive (pull-force - make sure you "$ git checkout my_branch" first!)
### Short aliases for our frequent commands ###
c = clone --recursive # Clone a repository including all submodules
l = config -l --show-origin
f = fetch
p = push
# Run this before every commit to make sure you don’t need to use the "undo" commands
# (Show the difference between the latest commit and the current state)
d = !"git diff-index --quiet HEAD -- || clear; git --no-pager diff --patch-with-stat"
pt = push --tags
st = status -s
cp = cherry-pick
ca = !"git add . && git commit -m"
cm = commit -m
cg = config --global
gl = !"git cg -l"
ic = !"git add . && git commit --allow-empty -m 'Initial commit'" # Motivation: When you "git init" Git doesn't create a main branch for you by default until you commit something!
up = !"git checkout main && git fetch upstream && git rebase upstream/main && git submodule-update" # First run "git remote add upstream <url>"
rao = remote add origin
here = !"f() { git init && git rao ${1} && git pull origin main && return 0; }; f"
last = log -1 HEAD --stat
main = !"git checkout main && git up"
branches = branch -a
tags = tag -n1 --list
last-tag = describe --tags --abbrev=0
stashes = stash list
remotes = remote -v
merge-test = "!f(){ git merge --no-commit --no-ff \"$1\"; git merge --abort; echo \"Merge aborted\"; };f " # Run this before merge to check for any conflicts
unmerged = diff --name-only --diff-filter=U
publish = !"git push --set-upstream origin $(git branch-name)"
unpublish = !"git push origin :$(git branch-name)"\
sub-repo = !sh -c 'git filter-branch --prune-empty --subdirectory-filter $1 main' -
human = name-rev --name-only --refs=refs/heads/*
# Initalize a repo and immediately add an empty commit, which makes rebase easier.
start = !"f() { git init && git ic; }; f" # run "git github-create" after "git start" if necessary
# Create a remote repo on GitHub (GitHub token needed: https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token)
# Note: make sure you have no unstaged changes before running this command!
# Note: If not working, make sure the directory is not placed on cloud drive, then delete the newly created repo on GitHub and run $ git remote remove origin, and try again.
github-create = !"f() { \
repo_name=\"$1\"; \
invalid_credentials=0; \
dir_name=`basename $(pwd)`; \
if [ \"$repo_name\" = \"\" ]; then \
echo \" Repo Name? (press enter to use \"$dir_name\")\"; \
read repo_name; \
fi; \
if [ \"$repo_name\" = \"\" ]; then \
repo_name=$dir_name; \
fi; \
username=$(git config github.user); \
if [ \"$username\" = \"\" ]; then \
echo \" ERROR - Could not find GitHub username, run 'git config --global github.user <username>'\"; \
invalid_credentials=1; \
fi; \
token=$MY_GITHUB_PAT; \
if [ \"$token\" = \"\" ]; then \
echo \" ERROR - Could not find GitHub personal access token (PAT), run 'echo "export MY_GITHUB_PAT=<your_token>" >> ~/.zshenv'\"; \
invalid_credentials=1; \
fi; \
type=$(git config github.tokentype); \
if [ \"$type\" = \"ssh\" ]; then \
conn_string="git@github.com:\"$username\"/\"$repo_name\".git"; \
elif [ \"$type\" = \"http\" ]; then \
conn_string="https://github.com/\"$username\"/\"$repo_name\".git"; \
else \
echo \" ERROR - Either token type was not entered correctly or is empty.\n It must be either 'ssh' or 'http'.\n Run git config --global github.tokentype <ssh|http>\"; \
invalid_credentials=1; \
fi; \
if [ \"$invalid_credentials\" -eq \"1\" ]; then \
return 1; \
fi; \
echo -n \" Creating GitHub repository '$repo_name' ...\"; \
curl -u \"$username:$token\" https://api.github.com/user/repos -d '{\"name\":\"'$repo_name'\"}' > /dev/null 2>&1; \
echo \" done.\"; \
echo -n \" Pushing local code to GitHub ...\"; \
git remote add origin \"$conn_string\" > /dev/null 2>&1; \
git push origin main > /dev/null 2>&1; \
echo \" done.\"; \
}; f"
# conflict / merges
# Usage: git ours/theirs <the-path(s)-of-the-files/directories-to-checkout>
ours = "!f() { git checkout --ours $@ && git add $@ && git cm "Merge OURS version into '$@'"; }; f"
theirs = "!f() { git checkout --theirs $@ && git add $@ && git cm "Merge THEIRS version into '$@'"; }; f"
# merge two Git repositories
merge-repo = !"f() { \
if [ $# -ne 1 ]; then \
echo \"Usage: git merge-repo <path/to/another-project> \n\"; \
echo \"If you want to put <another-project> into a subdirectory, run: \n\"; \
echo \" cd <path/to/another-project> \"; \
echo \" git filter-repo --to-subdirectory-filter <another-project> \n\"; \
echo \"before 'git merge-repo ...' \"; \
else \
another_project_name=`basename ${1}`; \
git remote add $another_project_name ${1}; \
git fetch $another_project_name --tags; \
git merge --allow-unrelated-histories $another_project_name/main; \
git remote remove $another_project_name; \
fi; \
}; f"
### SHELL SCRIPTING ALIASES ###
# Get the top level directory name
top-name = rev-parse --show-toplevel
# Get the current branch name
branch-name = rev-parse --abbrev-ref HEAD
# Get the upstream branch name
upstream-name = !git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)
### log ###
# View abbreviated SHA, description, and history graph of the latest 20 commits
oneline = log --graph --pretty=oneline -n 20 --abbrev-commit
changelog = log --pretty='- %s' > CHANGELOG.md # The "%s" corresponds to the commit title itself
lg1 = lg1-specific --all --simplify-by-decoration
lg2 = lg2-specific --all --simplify-by-decoration
lg3 = lg3-specific --all --simplify-by-decoration
lg1-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)'
lg2-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'
lg3-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(auto)%d%C(reset)%n'' %C(white)%s%C(reset)%n'' %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)'
# log like - we like this summarization our key performance indicators. Also aliased as 'log-like'.
ll = log --graph --topo-order --date-order --date=short --abbrev-commit --decorate --all --boundary --pretty=format:'%Cgreen%ad %Cred%h%Creset -%C(yellow)%d%Creset %s %Cblue[%cn]%Creset %Cblue%G?%Creset'
log-like = !"git ll"
# log like long - we like this summarization our key performance indicators. Also aliased as 'log-like-long'.
lll = log --graph --topo-order --date-order --date=iso8601-strict --no-abbrev-commit --abbrev=40 --decorate --all --boundary --pretty=format:'%Cgreen%ad %Cred%h%Creset -%C(yellow)%d%Creset %s %Cblue[%cn <%ce>]%Creset %Cblue%G?%Creset'
log-like-long = !"git lll"
graph = log --graph --all --simplify-by-decoration
hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
tree = log --graph --decorate --pretty=format:'%C(yellow)%h %Cred%cr %Cblue(%an)%C(cyan)%d%Creset %s' --abbrev-commit --all
### ls-files ###
# ls-files - show information about files in the index and the working tree; like Unix "ls" command.
ls = ls-files
# ls-ignored - list files that git has ignored.
ls-ignored = ls-files --others --i --exclude-standard
### grep-* ###
# Find text in any commit ever.
grep-all = !"f() { git rev-list --all | xargs git grep \"$@\"; }; f"
# Find text and group the output lines. A.k.a. 'gg'.
grep-group = grep --break --heading --line-number --color
### ALIAS MANAGEMENT ###
# Show our defined alias list
aliases = !"git config --get-regexp ^alias\\."
# Force an overwrite of local files with remote (main) branch
pull-force = !"git branch backup && git fetch --all && git reset --hard origin/${1-main}"
# Push to all remotes
push-to-all-remotes = !"git remote | xargs -I% -n1 git push %"
# Clear out the history of a git/github repository
clr = !"rm -rf .git"
clr-and-reinit = !"rm -rf .git && git start"
# Remove remote branch references that no longer exist, cleanup unnecessary git files, remove untracked files from the working tree and clear out stash
cleanup = !"git remote prune origin && git gc && git clean -dfx && git stash clear"
# Only for .gitconfig
edit-config = config --global --edit
update-config = "!f() { cd ~ && git add . && git commit -m 'Update .gitconfig' && git push ${1}; }; f"
# Only for .zshrc & .zsh_aliases
update-zsh = "!f() { cd ~ && git add . && git commit -m 'Update zsh configuration' && git push ${1}; }; f"
# Only for Windows PowerShell profile
update-PS-profile = "!f() { git add . && git commit -m 'Update PS profile' && git push ${1}; }; f"
# .gitignore related
ignore-unignored = !"git rm -r --cached --ignore-unmatch . && git add . && git commit -m '.gitignore fix' && git update-index --assume-unchanged .; git push;"
unignore-ignored = "!f() { git add -f ${1} && git add . && git commit -m '.gitignore fix' && git update-index --assume-unchanged .; git push; }; f"
### BRANCHES ###
# List all branches
br = branch -a
# List all branches sorted by last modified
b = "!git for-each-ref --sort='-authordate' --format='(%(authordate))%09%(objectname:short)%09%(refname)' refs/heads | sed -e 's-refs/heads/--'"
# Delete local or remote branches
del-local = branch --delete
del-remote = push origin --delete
# Remove branches that have already been merged into main or another branch provided as an argument
cleanup-merged-branches = "!f() { git branch --merged ${1:-main} | egrep -v \"(^\\*|${1:-main})\" | xargs — no-run-if-empty git branch -d; git remote -v update -p; }; f"
# Show GitHub repository url
url-github =!"echo "https://github.com/"`git config remote.${1-origin}.url` | sed -e 's#^.*@#https://#' -e 's#.git$##' -e 's#:#/#2'"
# Show the url to HEAD commit on GitHub
url-last-commit =!"sh -c 'HEAD=`git rev-parse HEAD` && SHA1=`[ "$0" = "sh" ] && echo $HEAD || echo $0` && echo `git url-github`"/commit/"${SHA1i}'"
# Open the repository on GitHub
# Usage: git open [upstream] (pass the remote name as an optional parameter, e.g., upstream, default is origin)
open = "!f() { REPO_URL=$(git config remote.${1-origin}.url | sed -e 's#^.*@#https://#' -e 's#.git$##' -e 's#:#/#2'); git web--browse $REPO_URL; }; f"
browse = !"git open"
# Keep gh-pages up to date with main branch
sync-ghpages = !"git checkout gh-pages && git rebase main && git push origin gh-pages && git checkout main"
# Submodule
submodule-add = !"f() { ([ $# = 1 ] || [ $# = 2 ]) && git submodule add ${1} ${2} && return 0 || \
echo \"Usage: git submodule-add <URL_to_Git_repo_of_submodule> [<path/to/submodule>]\" >&2 && return 1; }; f"
submodule-remove = !"f() { [ $# = 1 ] && git submodule deinit -f -- \"$1\" && rm -rf .git/modules/\"$1\" && git rm -f \"$1\" && return 0 || \
echo \"Usage: git submodule-remove <path/to/submodule>\" >&2 && return 1; }; f"
submodule-update = !"git submodule update --init --recursive --remote && git submodule-status"
submodule-status = submodule status --recursive
### Git Workflow (from https://haacked.com/archive/2014/07/28/github-flow-aliases/) ###
# 1
# Make sure the working directory is up-to-date with the origin before creating a new branch with some new work
up = !"git pull --rebase --prune $@ && git submodule-update"
# 2
# Switch to a branch, creating it if necessary
goto = "!f() { git checkout -b \"$1\" 2> /dev/null || git checkout \"$1\"; }; f"
# 3
# Commit all changes
ca = !"git add . && git commit -m"
# 4
save = !"git add -A && git commit -m 'SAVEPOINT'"
undo = reset HEAD~ --mixed
undo-hard = !"git reset --hard HEAD^"
# if you merely need to modify the previous commit
amend = commit --amend --all -m
# reset work that you "never committed" -> Don't do "git reset HEAD --hard"
wipe = "!f() { rev=$(git rev-parse ${1-HEAD}); \
git add -A && \
git commit --allow-empty -qm 'WIPE SAVEPOINT' && \
git reset $rev --hard; }; f"
### TOPIC BRANCH ###
# use a topic branch for a new feature, or a hotfix patch, or refactoring work, or some spike research, etc.
topic-base-branch-name = "!f() { \
git config --get gitalias.topic.base.branch.name || printf '%s\n' main; \
}; f"
topic-start = "!f() { \
topic_branch=\"$1\"; \
base_branch=$(git topic-base-branch-name); \
git checkout \"$base_branch\"; git pull; \
git checkout -b \"$topic_branch\" \"$base_branch\"; \
git push --set-upstream origin \"$topic_branch\"; \
}; f"
topic-rename = "!f() { \
new_branch=\"$1\"; \
old_branch=$(git branch-name); \
git branch --move \"$old_branch\" \"$new_branch\"; \
git push origin \":$old_branch\" \"$new_branch\"; \
}; f"
topic-sync = "!f() { \
topic_branch=$(git branch-name); \
base_branch=$(git topic-base-branch-name); \
if [ \"$topic_branch\" = \"$base_branch\" ]; then \
printf \"You are asking to do git topic-sync,\n\"; \
printf \"but you are not currently on a topic branch;\n\"; \
printf \"you are on the base branch: $base_branch.\n\"; \
printf \"Please checkout the topic branch that you want,\n\"; \
printf \"then retry the git topic-sync command.\n\"; \
else \
git pull --rebase origin \"$topic_branch\"; \
git push; \
fi; \
}; f"
topic-merge = "!f() { \
topic_branch=$(git branch-name); \
base_branch=$(git topic-base-branch-name); \
if [ \"$topic_branch\" = \"$base_branch\" ]; then \
printf \"You are asking to do git topic-merge,\n\"; \
printf \"but you are not currently on a topic branch;\n\"; \
printf \"you are on the base branch: $base_branch.\n\"; \
printf \"Please checkout the topic branch that you want,\n\"; \
printf \"then retry the git topic-merge command.\n\"; \
else \
git goto \"$base_branch\"; \
git merge \"$topic_branch\"; \
git ca "Merge \"$topic_branch\" into \"$base_branch\" branch"; \
fi; \
}; f"
topic-stop = "!f() { \
topic_branch=$(git branch-name); \
base_branch=$(git topic-base-branch-name); \
if [ \"$topic_branch\" = \"$base_branch\" ]; then \
printf \"You are asking to do git topic-stop,\n\"; \
printf \"but you are not currently on a topic branch;\n\"; \
printf \"you are on the base branch: $base_branch.\n\"; \
printf \"Please checkout the topic branch that you want,\n\"; \
printf \"then retry the git topic-stop command.\n\"; \
else \
git push; \
git checkout \"$base_branch\"; \
git branch --delete \"$topic_branch\"; \
git push origin \":$topic_branch\"; \
fi; \
}; f"
# Ignore all untracked files by appending them to .gitignore:
ignore = "!git status | grep -P \"^\\t\" | grep -vF .gitignore | sed \"s/^\\t//\" >> .gitignore"
# Summary: print a helpful summary of some typical metrics
summary = "!f() { \
printf \"Summary of this branch...\n\"; \
printf \"%s\n\" $(git rev-parse --abbrev-ref HEAD); \
printf \"%s first commit timestamp\n\" $(git log --date-order --format=%cI | tail -1); \
printf \"%s latest commit timestamp\n\" $(git log -1 --date-order --format=%cI); \
printf \"%d commit count\n\" $(git rev-list --count HEAD); \
printf \"%d date count\n\" $(git log --format=oneline --format=\"%ad\" --date=format:\"%Y-%m-%d\" | awk '{a[$0]=1}END{for(i in a){n++;} print n}'); \
printf \"%d tag count\n\" $(git tag | wc -l); \
printf \"%d author count\n\" $(git log --format=oneline --format=\"%aE\" | awk '{a[$0]=1}END{for(i in a){n++;} print n}'); \
printf \"%d committer count\n\" $(git log --format=oneline --format=\"%cE\" | awk '{a[$0]=1}END{for(i in a){n++;} print n}'); \
printf \"%d local branch count\n\" $(git branch | grep -v \" -> \" | wc -l); \
printf \"%d remote branch count\n\" $(git branch -r | grep -v \" -> \" | wc -l); \
printf \"\nSummary of this directory...\n\"; \
printf \"%s\n\" $(pwd); \
printf \"%d file count via git ls-files\n\" $(git ls-files | wc -l); \
printf \"%d file count via find command\n\" $(find . | wc -l); \
printf \"%d disk usage\n\" $(du -s | awk '{print $1}'); \
printf \"\nMost-active authors, with commit count and %%...\n\"; git log-of-count-and-email | head -7; \
printf \"\nMost-active dates, with commit count and %%...\n\"; git log-of-count-and-day | head -7; \
printf \"\nMost-active files, with churn count\n\"; git churn | head -7; \
}; f"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment