Peter Weightman
Back

My Git Aliases (May 2021)

Git Aliases

Intro

This post will go through my most used git aliases. Aliases can be used to save time on your most used commands, but also can be handy for saving you time trying to search stack overflow for rarely-used but tricky commands. I try to get in the habit of creating an alias any time I find myself using a command a lot, or if I google how to do something and come across a command that I'll probably forget before the next time I need it.

To find your most used commands you can use: history | awk 'BEGIN {FS="[ \t]+|\\|"} {print $3,$4}' | sort | uniq -c | sort -n. Within that code, if you do print $3 it'll just print the first word of your command e.g. git or vim, doing print $3,$4 will print the second word too, e.g. git status, or git log.

The Aliases

  1. git lo, git lop, and git mo
    • These are all shorthand's for working with remote branches. Let's say someone has pushed to feature-123, and you want to review and merge it. You can pull/fetch the changes but unless you're already on that branch, your local branch won't be up to date. To view the most up to date version of the branch without changing to it you'll have to actually look at origin/feature-123.
    • Usage: git lo feature-123 will run git log origin/feature-123, which will show the commits on the remote branch.
    • Usage: git lop feature-123 will run git log -p origin/feature-123, which will show the code change for each commit.
    • Usage: git mo feature-123 will run git merge origin/feature-123, which will merge the remote branch.
  2. s
    • This is an alias for git status, which is the command for knowing the current state of things, so it's useful to be able to run it with a single letter.
  3. gco -b, gco -, and gco --
    • gco is an alias for git checkout which is another useful command.
    • Usage: gco -b feature-123 will run git checkout -b feature-123, which will create a branch called feature-123
    • Usage: gco - will run git checkout -, which will checkout the previous branch you were on.
    • Usage: gco -- path/to/file will run git checkout -- path/to/file, which will get rid of any unstated changes in the file at path/to/file.
  4. git short-hash
    • Usage: git short-hash <commit-hash> will run git rev-parse --short <commit-hash>, which will give you a shortened version of the commit hash you give it.
    • As far as I'm aware, it doesn't serve much of a purpose other than making the hashes you share look nicer.
  5. git file-change-commits, git file-changes, and git show-file
    • Usage: git file-change-commits path/to/file will run git log --all --follow path/to/file, which will show all the commits from any branch that changes the specified file (even if that file has been renamed in the past).
    • Usage: git file-changes path/to/file will run the same as above but with the -p flag, which will show the code changes in each commit.
    • Usage: git show-file some-branch path/to/file will run git show some-branch:path/to/file, which will show you what the specified file looks like on the specified branch.
    • These are useful for when you know something has changed in a file in the past but can't remember when/why, if you know you changed the file on a specific branch, or if you're trying to resolve merge conflicts.
  6. git branch-commit-diffs, git branch-code-diffs, and git branch-file-diffs
    • These are all about finding diffs between two branches.
    • Usage: git branch-commit-diffs branch-1 branch-2 will run git log --oneline --graph --decorate --abbrev-commit branch-2..branch-1;. You can also leave off the second branch and it'll use your current commit instead. This will show you a list of commits that are on branch-1 and not on branch-2.
    • Usage: git branch-code-diffs branch-1 branch-2 will run git diff branch-2..branch-1;. This will show you the diff of the code that's on branch-1 but not on branch-2.
    • Usage: git branch-file-diffs branch-1 branch-2 path/to/file will run git diff branch-2..branch-1 -- path/to/file;. This will do the same as the previous command but will only show you the code in the file specified.
  7. git nb
    • Usage: git nb hotfix-123 will run git fetch && git checkout main && git checkout -b hotfix-123;. You could also do git nb hotfix-123 v1.0.0 which would run git fetch && git checkout v1.0.0 && git checkout -b hotfix-123
    • This is useful for creating a new branch when you want it to be branched off somewhere different to your current location. The default will be the main branch but you can change it to be a different place.
  8. git branched-off, and git released-in
    • Usage: git branched-off feature-123 will run git describe --tags --abbrev=0 --match 'v*' feature-123;, which will find the closest tag that starts with 'v' (e.g. v1.0.0) before the point you've specified.
    • Usage: git released-in feature-123 will run git tag --contains feature-123 'v*' | head -n 1;, which will find the closest tag that starts with 'v' (e.g. v1.0.0) after the point you've specified.
    • These rely on you creating tags when you release a new version and allow you to check the version a branch is ahead of, and the version it was released in (if at all).
  9. stash, spop, spull, and spush
    • Usage: stash will run git stash, which will just stash all un-comitted, tracked changes, and you could do stash save "message" to save with a message.
    • Usage: spop will run git stash pop, which will pop the latest stash so the changes are back in your working directory.
    • Usage: spull will run git stash && git pull --rebase, which will stash your changes and then pull.
    • Usage: spush will run git push && git stash pop, which will pushed your commits and then unstash your changes.
    • This means you can commit some things and push even when you have other WIP changes by doing spull followed by spush.
  10. git pset
    • Usage: git pset will run git push --set-upstream origin <current_branch_name>;. This will push a newly created branch to the remote.
  11. git rm-branch
    • Usage: git rm-branch branch-to-delete will run git branch -D branch-to-delete && git push -d origin branch-to-delete, which will first delete your local copy of the branch and then the remote copy.
  12. git recent
    • This will run git for-each-ref --count=10 --sort=-committerdate refs/heads/ --format="%(refname:short)", which will list the 10 most recent branches that you were on sorted by last commit.
  13. git recap, and git today
    • These are useful for reminding yourself of what you've been up to which is handy for meetings where you talk about what you've been working on.
    • Usage: git recap Peter will run git log --all --oneline --no-merges --author=Peter;, you can leave off the name and it will default to using whatever your git config email is set to. This will give you a list of all the commits you've made.
    • Usage: git today Peter is the same as above except it limits it to only commits made today.
  14. git reset-to-origin
    • Usage: git reset-to-origin, will run git reset --hard origin/<current-branch>, where <current-branch> is the name of your current branch. It will get rid of any local changes you have, so that your local branch matches the remote branch.
  15. git edit, and git uncommit
    • Usage: git edit will run git rebase -i, which will allow you to (among other things) change commit messages, and squash multiple commits into one.
    • Usage: git uncommit will run git reset --soft HEAD^, which will basically undo the act of committing. Your changes will still be staged but will not be committed.
  16. isMerged
    • Usage: isMerged HEAD feature-123, will run a function to check if feature-123 has been merged into HEAD, i.e. your current location. You could specify another location though.
  17. git stats
    • Usage: git stats will run git shortlog -sn --all --no-merges, which will show you a list of committers and how many commits they have, excluding merge commits.

Aliases

~/.gitconfig

[alias]
	lo = "!f() { git log origin/$1; }; f"
	lop = "!f() { git log -p origin/$1; }; f"
	mo = "!f() { git merge origin/$1; }; f"

	recap = "!f() { git log --all --oneline --no-merges --author=${1-$(git config user.email)}; }; f"
	recent = for-each-ref --count=10 --sort=-committerdate refs/heads/ --format="%(refname:short)"
	today = "!f() { git log --all --since=00:00:00 --oneline --no-merges --author=${1-$(git config user.email)}; }; f"
	stats = shortlog -sn --all --no-merges

	branched-off = "!f() { git describe --tags --abbrev=0 --match 'v*' ${1-HEAD}; }; f"
	released-in = "!f() { git tag --contains ${1-HEAD} 'v*' | head -n 1; }; f"

	branch-code-diffs = "!f() { git diff ${2-HEAD}..$1; }; f"
	branch-commit-diffs = "!f() { git log --oneline --graph --decorate --abbrev-commit ${2-HEAD}..$1; }; f"
	branch-file-diffs = "!f() { git diff ${3-HEAD}..$2 -- $1; }; f"
	file-change-commits = "!f() { git log --all --follow $1; }; f"
	file-changes = "!f() { git log -p --all --follow $1; }; f"
	show-file = "!f() { git show $1:$2; }; f"

	nb = "!f() { git fetch && git checkout ${2-main} && git checkout -b $1; }; f"
	reset-to-origin = "!f() { git reset --hard origin/${1-$(git rev-parse --abbrev-ref HEAD)}; }; f"
	pset = "!f() { git push --set-upstream origin ${1-$(git rev-parse --abbrev-ref HEAD)}; }; f"
	rm-branch = "!f() { git branch -D $1 && git push -d origin $1; }; f"
	edit = rebase -i
	uncommit = reset --soft HEAD^
	mv-tag = "!f() { git tag -d $1 && git push origin :refs/tags/$1 && git tag $1 ${2-HEAD} && git push origin $1; }; f"

	short-hash = rev-parse --short

~/.zshrc

alias s='git status'
alias gco='git checkout'
alias stash='git stash'
alias spop='git stash pop'
alias spull='git stash && git pull --rebase'
alias spush='git push && git stash pop'
isMerged() {
	merge_destination_branch=$1
	merge_source_branch=$2

	merge_base=$(git merge-base $merge_destination_branch $merge_source_branch)
	merge_source_current_commit=$(git rev-parse $merge_source_branch)
	if [[ $merge-base = $merge_source_current_commit ]]
	then
		echo $merge_source_branch is merged into $merge_destination_branch
		return 0
	else
		echo $merge_source_branch is not merged into $merge_destination_branch
		return 1
	fi
}