Configure Git (Note: This is a one-time setup.):
mkdir -p ~/.config/git
touch ~/.config/git/config
git config --global user.name "First Last"
git config --global user.email "[email protected]"
# Default branch name
git config --global init.defaultBranch main
# Prevent pushes directly to main
#git config --global branch.main.pushRemote no_push
#git config --global branch.master.pushRemote no_push
# Default editor
git config --global core.editor "vim" # Vim
#git config --global core.editor "code --wait" # VS Code
git config --global core.excludesfile "$XDG_CONFIG_HOME/git/.gitignore_global"
git config --global core.attributesfile "$XDG_CONFIG_HOME/git/.gitattributes_global"
git config --global core.eol lf
git config --global core.autocrlf input
git config --global core.ignorecase false
git config --global core.quotepath false
git config --global core.fscache true
#git config --global core.preloadindex true
#git config --global gc.auto 256
git config --global --add safe.directory "*"
# GPG
#git config --global user.signingkey XXXXX
#git config --global commit.gpgsign true
#git config --global tag.gpgSign true
#git config --global gpg.format ssh
#git config --global gpg.program gpg
# Disable all the Git help messages
#git config --global advice.pushUpdateRejected false
#git config --global advice.pushNonFFCurrent false
#git config --global advice.pushNonFFMatching false
#git config --global advice.pushAlreadyExists false
#git config --global advice.pushFetchFirst false
#git config --global advice.pushNeedsForce false
#git config --global advice.statusHints false
#git config --global advice.statusUoption false
#git config --global advice.commitBeforeMerge false
#git config --global advice.resolveConflict false
#git config --global advice.implicitIdentity false
#git config --global advice.detachedHead false
#git config --global advice.amWorkDir false
#git config --global advice.rmHints false
git config --global color.ui auto
git config --global format.pretty "format:%C(yellow)%h%Creset %C(blue)%an%Creset %C(green)%ar%Creset %s"
git config --global color.diff always
git config --global status.showUntrackedFiles all
git config --global status.branch true
git config --global status.short true
# https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault
git config --global push.default simple
git config --global push.autoSetupRemote true
git config --global push.useForceIfIncludes true
git config --global pull.rebase true
git config --global rebase.autoStash true
git config --global fetch.prune true
git config --global remote.origin.prune true
git config --global commit.verbose true
# https://blog.gitbutler.com/git-tips-2-new-stuff-in-git/#some-git-branch-stuff
git config --global branch.sort -committerdate
git config --global column.ui auto
# https://blog.gitbutler.com/git-tips-1-theres-a-git-config-for-that/#reuse-recorded-resolution
git config --global rerere.enabled true
git config --global rerere.autoUpdate true
git config --global tag.sort version:refname
git config --global merge.conflictStyle zdiff3
git config --global merge.ff only
git config --global pull.ff only
git config --global diff.algorithm histogram
git config --global diff.renames true
# Helpful Aliases
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.a 'add .'
git config --global alias.aa 'add -A'
git config --global alias.amend 'commit --amend --no-edit'
git config --global alias.ri 'rebase -i'
git config --global alias.unstage 'reset HEAD --'
git config --global alias.undo 'reset HEAD~1 --mixed'
git config --global alias.nuke 'reset HEAD~1 --hard'
git config --global alias.branches 'branch -a --sort=-committerdate'
git config --global alias.dl 'diff HEAD~1'
git config --global alias.up '!git fetch && git rebase origin/$(git symbolic-ref --short HEAD)'
git config --global alias.publish '!git push -u origin $(git branch --show-current)'
git config --global alias.cleanup '!git branch --merged | grep -v "\\*\\|main\\|master" | xargs -n 1 git branch -d'
git config --global alias.save '!git add -A && git commit -m "SAVEPOINT"'
git config --global alias.wipe '!git add -A && git commit -qm "WIPE SAVEPOINT" && git reset HEAD~1 --hard'
git config --global alias.last 'log -1 HEAD --stat'
git config --global alias.recent "log --oneline -10"
git config --global alias.grep "log --grep"
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
git config --global alias.tree "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all"
Authenticate with GitHub CLI:
gh auth login
To check your aliases:
git config --get-regexp alias
brew install git-lfs
Update global git config:
git lfs install
Update system git config:
sudo git lfs install --system
Clone repo and setup:
git clone https://github.com/<username>/<repo>
cd repo
# OR use the GitHub CLI to clone the repo
gh repo clone thimslugga/repo
cd repo
Update the main branch and then create feature branch:
# ALWAYS branch from main
git checkout main
git pull origin main
# OR you can use gh as alternative
gh repo sync # syncs all branches
# (Optional) Check existing worktrees
git worktree list
# Checkout feature branch
git checkout -b feature/<feature_name>
Branch Naming Convention
feature/<feature-name>
bugfix/<bug-fix-description>
hotfix/<security-patch>
docs/<update-readme>
Make changes, then stage and commit:
# Stage changes
git add .
# Commit your changes, use one of these types: feat, fix, docs, style, refactor, test, chore
git commit -m "<type>: <description>"
# OR for a longer commit message
git commit -m "<type>: brief description
Optional longer explanation of what changed and why.
Closes #123"
Example types to use:
feat:
fix:
docs:
chore:
style:
build:
test:
refactor:
Push and create PR in one go:
git push -u origin feature/<feature_name>
gh pr create --title "<title_goes_here>" --body "<body_goes_here>"
Check PR status and reviews:
gh pr status
gh pr view # shows current branches PR
Address PR review feedback using the following:
git add .
git commit -m "fix: addresses review comments"
git push
Pull in main branch changes if needed:
# Regularly sync your branch
git checkout main
git pull origin main
git checkout feature/<feature_name>
git rebase main # Apply your changes on top of latest main
# Alternative is to merge instead of rebase
git merge main # Keeps your branch history intact
Merge PR via GitHub CLI:
gh pr merge <pr_number> --squash --delete-branch
#gh pr merge --merge # or --squash or --rebase
git pull
git branch -d feature/<feature_name>
git remote prune origin
Sync main branch:
git checkout main
git pull origin main
git log --oneline -5 # Verify merge
Interactive rebase:
git rebase -i HEAD~n
Change "pick" to "squash" (or "s") for commits you want to combine with the previous commit. After you save and close, you'll be met with another editor to edit the combined commit message. Save and close to complete the process.
git log
(Simpler Alternative) soft reset method:
git reset --soft HEAD~n
git commit -m "New combined commit message"
# Save changes
git stash -m "stash before sync"
git checkout origin main
git pull origin main
git rebase origin main
# Apply the top stashed element and then remove it from the stack
git stash pop
git lg
If you made changes, staged and commited them locally but realized you forgot to sync:
# Fetch the latest from remote
git fetch origin
# Rebase your commit(s) on top of the latest main
git rebase origin/main
# Check the status
git status
If you made changes, staged them made commit but realized you forgot to sync and need to start fresh:
# Undo the commit but keep changes staged
git reset --soft HEAD~1
# Now sync
git fetch origin
git rebase origin/main
# Now you should be safe to commit again
git commit -m "commit message"
# Check the status
git status
For every single little new change, you will want to perform the following steps.
Make sure you pull the latest version from the main:
git checkout main
git pull --rebase
Create a new feature branch from the latest main code:
git checkout -b feat/<new_feature_branch>
Make change and commit in the new-feature branch
git add <path_to_changed_file>
git commit -m "feat: brief comment about commit"
List and filter PRs:
gh pr list --state open --author "@me"
gh pr list --label "bug" --assignee "@me"
Review PRs:
gh pr checkout 42 # check out PR #42 locally
gh pr diff
gh pr review --approve
gh pr review --request-changes --body "Please fix the error handling"
# Starting work
gh pr comment <pr_number> --body "🚀 Starting: <task_description>"
# Progress updates (every 30-60 minutes)
gh pr comment <pr_number> --body "🔧 Progress: <completed_items>"
# Completing tasks
gh pr comment <pr_number> --body "✅ Completed: <task_description>"
# Encountering blockers
gh pr comment <pr_number> --body "⚠️ Blocker: <issue_description>"