Skip to content

Instantly share code, notes, and snippets.

@rocketraman
Last active November 7, 2024 21:42
Show Gist options
  • Save rocketraman/1fdc93feb30aa00f6f3a9d7d732102a9 to your computer and use it in GitHub Desktop.
Save rocketraman/1fdc93feb30aa00f6f3a9d7d732102a9 to your computer and use it in GitHub Desktop.
.gitconfig aliases useful for gitworkflow (https://github.com/rocketraman/gitworkflow)
[alias]
# Basically `log --oneline --decorate --graph` with different colors and some additional info (author and date)
lg = log --graph --abbrev-commit --decorate --format=format:'%C(yellow)%h%C(reset) %C(normal)%s%C(reset) %C(dim white)%an%C(reset) %C(dim blue)(%ar)%C(reset) %C(dim black)%d%C(reset)'
# lg (see above) with --first-parent
lgp = log --graph --abbrev-commit --decorate --format=format:'%C(yellow)%h%C(reset) %C(normal)%s%C(reset) %C(dim white)%an%C(reset) %C(dim blue)(%ar)%C(reset) %C(dim black)%d%C(reset)' --first-parent
# https://stackoverflow.com/questions/61510067/show-specific-commits-in-git-log-in-context-of-other-commits
hl = "!f() { cd -- ${GIT_PREFIX:-.}; grep --color -E \"$(git log --pretty=%h \"$@\" | tr '\n' '|')\" || true; }; f"
hlp = "!f() { cd -- ${GIT_PREFIX:-.}; less -R -p $(git log --pretty=%h \"$@\" | tr '\n' '|'); }; f"
showp = show --first-parent
# List every branch, local and remote, in order of most recent to oldest commit, showing the branch's last commit and some last commit meta-data
br = for-each-ref --sort=-committerdate refs/heads/ refs/remotes/origin/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))' -
m = merge --no-ff
# Like m/merge but automatically adds origin/ for remote branches, and makes the log message consistent with a local branch merge
mb = "!f() { : git merge; branch=\"$1\"; if [[ $branch != \"origin/*\" ]]; then branch=\"origin/$branch\"; fi; git merge --no-ff $branch -m \"Merge branch '$(echo $1 | sed -e 's|origin/||g')' into $(git symbolic-ref HEAD | sed -e 's|refs/heads/||g')\"; }; f"
# tomerge <branch> <regex> tells you which branches matching <regex> have not been merged into <branch> yet
tomerge = !sh -c 'git branch -r --no-merged ${2:-HEAD} | grep -Ev "HEAD" | grep -Ev \"(\\*|master|maint|next|proposed|demo-stable)\" | grep ${1:-.}' -
# show topics (branches) matching the ai/description format
topics = "!f() { git branch --sort=committerdate -r | sed -e 's|remotes/||g' -e 's|origin/||g' | grep -E \"[a-z][a-z]?[a-z]?/.*\" | cut -c3- | grep -v -E '^(archive|backup)/' | uniq | grep -v HEAD ; }; f"
ff = !sh -c 'branch=$(git symbolic-ref HEAD | cut -d '/' -f 3-) && git merge --ff-only origin/$branch' -
fap = fetch --all -p -t
diffp = "!f() { : diff; [ \"$GIT_PREFIX\" != \"\" ] && cd "$GIT_PREFIX"; git diff --color $@ | diff-so-fancy | less --tabs=2 --pattern='^(added|deleted|modified): ' -RFX; }; f"
poh = push origin HEAD
pouh = push origin -u HEAD
pouph = push origin -u +HEAD
# The oldest ancestor between an integration branch (by default, master) and a topic branch (by default HEAD)
# e.g. git oldest-ancestor master ai/topic
# See http://stackoverflow.com/a/4991675/430128
oldest-ancestor = !bash -c 'diff --old-line-format= --new-line-format= <(git rev-list --first-parent \"${1:-master}\") <(git rev-list --first-parent \"${2:-HEAD}\") | head -1' -
# branchx is relative to the second param (the current branch by default)
# use "topicx" for branches relative to a gitworkflows integration branch
branchlg = !sh -c \"git lg $(git oldest-ancestor $1 ${2:-HEAD})..$1\" -
branchlog = !sh -c \"git log $(git oldest-ancestor $1 ${2:-HEAD})..$1\" -
branchdiff = !sh -c \"git diff $(git oldest-ancestor $1 ${2:-HEAD})..$1\" -
branchstat = !sh -c \"git --no-pager diff --stat $(git oldest-ancestor $1 ${2:-HEAD})..$1\" -
# topiclg is always relative to the second param (or master by default), and always assumes origin for the topic (except if HEAD)
# branchx is more general (doesn't assume anything), but topicx is useful for gitworkflows
# If the base of the topic was `maint` instead of `master`, you need to specify `maint` as the second param
topiclg = !sh -c \"git lg $(git oldest-ancestor origin/$(echo $1 | sed -e 's|origin/||g') ${2:-master})..origin/$(echo $1 | sed -e 's|origin/||g')\" -
topiclgp = !sh -c \"git lgp $(git oldest-ancestor origin/$(echo $1 | sed -e 's|origin/||g') ${2:-master})..origin/$(echo $1 | sed -e 's|origin/||g')\" -
topiclog = !sh -c \"git log $(git oldest-ancestor origin/$(echo $1 | sed -e 's|origin/||g') ${2:-master})..origin/$(echo $1 | sed -e 's|origin/||g')\" -
topiclogp = !sh -c \"git log --first-parent $(git oldest-ancestor origin/$(echo $1 | sed -e 's|origin/||g') ${2:-master})..origin/$(echo $1 | sed -e 's|origin/||g')\" -
topicdiff = !sh -c \"git diff $(git oldest-ancestor origin/$(echo $1 | sed -e 's|origin/||g') ${2:-master})..origin/$(echo $1 | sed -e 's|origin/||g')\" -
topicstat = !sh -c \"git --no-pager diff --stat $(git oldest-ancestor origin/$(echo $1 | sed -e 's|origin/||g') ${2:-master})..origin/$(echo $1 | sed -e 's|origin/||g')\" -
# Same as topic... aliases above, but operates on local topics (or HEAD if no arg specified)
topicllg = !sh -c \"git lg $(git oldest-ancestor ${1:-HEAD} ${2:-master})..${1:-HEAD}\" -
topicllgp = !sh -c \"git lgp $(git oldest-ancestor ${1:-HEAD} ${2:-master})..${1:-HEAD}\" -
topicllog = !sh -c \"git log $(git oldest-ancestor ${1:-HEAD} ${2:-master})..${1:-HEAD}\" -
topicllogp = !sh -c \"git log --first-parent $(git oldest-ancestor ${1:-HEAD} ${2:-master})..${1:-HEAD}\" -
topicldiff = !sh -c \"git diff $(git oldest-ancestor ${1:-HEAD} ${2:-master})..${1:-HEAD}\" -
topiclstat = !sh -c \"git --no-pager diff --stat $(git oldest-ancestor ${1:-HEAD} ${2:-master})..${1:-HEAD}\" -
# These also work on integration branches
branchllg = topicllg
branchllgp = topicllgp
branchllog = topicllg
branchllogp = topicllgp
branchldiff = topicldiff
branchlstat = topiclstat
# Log of already merged topic -- pass the topic merge commit as a parameter, and the fork branch as a second param (master by default)
# If the base of the branch was `maint` instead of `master`, you need to specify `maint` as the second param
mergedtopiclg = !sh -c \"git lg $(git oldest-ancestor $1^2 ${2:-master})..$1^2\" -
# Similar to mergedtopiclg but shows only the merged revs for a particular merge, not the entire topic (for example, if the same topic
# is merged multiple times)
mergedrevs = !sh -c \"git lg $1^-\" -
# Topics merged into a topic
mergedtopicsintotopic = !sh -c \"git topiclgp $1 | grep Merge | sed -e 's/.*\\(SP-[0-9]*\\).*/\\1/g' | sort | uniq\" -
# Merged branches into a range
mergedinto = "!f() { git lgp $1 | sed -e \"s|.*'\\(.*\\)'.*|\\1|g\" -e \"s|origin/||g\" | awk '!x[$0]++' | tac ; }; f"
# gitworkflows addons for topic notes
# Push/fetch branchnotes
# git config --add remote.origin.push '+refs/notes/branchnote:refs/notes/branchnote'
# git config --add remote.origin.fetch '+refs/notes/branchnote:refs/notes/branchnote'
branchnote = notes --ref=branchnote append
branchnoterm = notes --ref=branchnote remove
# Status of all topic branches (what is their state, and any topic notes)
# - : proposed
# + : next
# * : maint
# = : master
# . : no integration branch
where = "!bash -c 'while read topic; do contains=$(git branch -r --contains origin/$topic); if grep -q origin/maint <(echo "$contains"); then echo "\\* $topic"; elif grep -q origin/master <(echo "$contains"); then echo "= $topic"; elif grep -q origin/next <(echo "$contains"); then echo "+ $topic"; elif grep -q origin/proposed <(echo "$contains"); then echo "- $topic"; else echo ". $topic"; fi; if git notes --ref=branchnote list origin/$topic &> /dev/null; then echo -e "\\\\x20\\\\x20$(git notes --ref=branchnote show origin/$topic)"; fi; done < <(git topics)'"
# Misc
find = log --color --source -S
ignore = update-index --skip-worktree
unignore = update-index --no-skip-worktree
ignored = !git ls-files -v | grep "^S " | cut -c3-
rmbranch = "!f(){ : branch git branch -d ${1}; git push origin --delete ${1}; };f"
patch = --no-pager diff --no-color
chlog = !sh -c 'git log $1...$2 --pretty=format:\"* %s [view commit](http://github.com/$3/$4/commit/%H) \"' -
rmb = "!f() { gitrmb \"$@\"; }; f"
stash-all = stash push --include-untracked
stash-index = "!f() { \
git stash push --quiet --keep-index -m \"temp for stash-index\" && \
git stash push \"$@\" && \
git stash pop --quiet stash@{1} && \
git stash show -p | git apply -R; }; f"
stash-working = "!f() { \
git commit --quiet --no-verify -m \"temp for stash-working\" && \
git stash push \"$@\" && \
git reset --quiet --soft HEAD~1; }; f"
undo = reset --soft HEAD^
new = !sh -c 'git lg $1@{1}..$1@{0} "$@"'
blameconflict = blame -L '/^<<<</,/^>>>>/'
check = !sh -c 'git --no-pager diff --check "$@"' {}
# The different cases are:
# - dirty tree and dirty index
# - dirty tree and clean index
# - clean tree and dirty index
#
# We have to consider separate cases because the 'git rebase
# --whitespace=fix' is not compatible with empty commits (adding
# '--keep-empty' makes Git not fix the whitespace :P).
fixws-global-tree-and-index = !"\
if (! git diff-files --quiet .) && \
(! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git add -u :/ && \
git commit -m FIXWS_SAVE_TREE && \
git rebase --whitespace=fix HEAD~2 && \
git reset HEAD~ && \
git reset --soft HEAD~ ; \
elif (! git diff-files --quiet .) ; then \
git add -u :/ && \
git commit -m FIXWS_SAVE_TREE && \
git rebase --whitespace=fix HEAD~ && \
git reset HEAD~ ; \
elif (! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git rebase --whitespace=fix HEAD~ && \
git reset --soft HEAD~ ; \
fi"
@rocketraman
Copy link
Author

Thanks @phil-blain. On that note, I've just pushed a bunch of changes:

* f9e3539 `stash-index` and `stash-working` Raman Gupta (4 minutes ago) 
* 2a412bc Useful push aliases Raman Gupta (6 minutes ago) 
* 13a50ce Simplifying and documenting `where` Raman Gupta (7 minutes ago) 
* e00dbc5 `topiclog` and `topiclogp` analogues to `topiclg` and `topiclgp` Raman Gupta (7 minutes ago) 
* c6a078e Default to no-pager in various cases Raman Gupta (35 minutes ago) 
* f25f359 `branchx` analogs to `topicx` aliases Raman Gupta (36 minutes ago) 
* ff4d712 Minor color change to lg/lgp Raman Gupta (38 minutes ago) 
* a577fd9 Exclude archive and backup 'folders' from topic list Raman Gupta (39 minutes ago)

@phil-blain
Copy link

Hey @rocketraman! I think it could be good to document (either here or on https://github.com/rocketraman/gitworkflow) in what cases

git mergedtopiclg <hash> upstream/master

gives a different answer than a simple

git lg <hash>^-

which in addition to also showing the merge commit, shows only the changes which were actually merged in  <hash>, i.e. if the same branch was merged several times, with additional commits each time, mergedtopiclg always shows all commits on the branch whereas the <rev>^- syntax only shows which commits were merged in <rev>.

What do you think?

@rocketraman
Copy link
Author

@phil-blain, that's cool. I wasn't aware of that syntax. For others that syntax might be new for as well the <rev>^-[<n>] syntax is for the log of rev, including rev itself, and excluding the nth parent (where n defaults to 1). See https://git-scm.com/docs/gitrevisions#_other_rev_parent_shorthand_notations. Thanks for the information.

@rocketraman
Copy link
Author

Added mergedrevs alias with the <hash>^- syntax suggested by @phil-blain.

@rocketraman
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment