[user] ; Don't try to guess `user.name` and `user.email`. useConfigOnly = true [include] path = ~/.gitconfig-user [core] ; If the `LESS` environment variable is unset, Git (naively) prepends ; `LESS=FRX` to the shell expression given in `pager` (or it's ; default). `X` disables sending termcap (alternate screen) ; initialization and deinitialization strings to the terminal, which ; disables mouse scrolling and makes long text scroll past previous ; context. ; pager = LESS=FR less pager = diff-highlight | LESS=FR less ; TODO: E.g. `attributesFile` defaults to ; `$XDG_CONFIG_HOME/git/attributes`. Maybe this is a better place to ; put these? hooksPath = ~/.githooks excludesFile = ~/.gitignore attributesFile = ~/.gitattributes ; Print paths verbatim (e.g. UTF-8). quotePath = false ; Disable newline conversion (mangling). This relies on editors *also* ; not doing any conversions or else you will get huge useless diffs. ; Also be aware of text files copied verbatim from somewhere else such ; as the internet. The Git default of having only LF in commits (autocrlf = false), but sometimes . ; autocrlf = input ; If we re-enable conversion (see above), reject on failed roundtrip. safecrlf = true ; [pager] ; ; As suggested in `contrib/diff-highlight/README`, except as explained ; ; in `core.pager` above. ; log = diff-highlight | less -+X ; show = diff-highlight | less -+X ; diff = diff-highlight | less -+X [interactive] ; TODO: It is untested if this is needed or happens by virtue of ; `core.pager`. Also untested if it has any ill effects. diffFilter = diff-highlight [init] templateDir = ~/.gittemplate defaultBranch = master ; defaultBranch = main [remote] pushDefault = origin [push] default = current ; This obviates `git push --set-upstream`. ; In the past, `current` was commented out and we used `upstream` ; instead, unsure why. ; default = upstream recurseSubmodules = check autoSetupRemote = true ; Git 2.37 [branch] autoSetupMerge = always autoSetupRebase = always [fetch] prune = true pruneTags = true [rebase] autoSquash = true autoStash = true rebaseMerges = true updateRefs = true missingCommitsCheck = error instructionFormat = %s%nexec GIT_COMMITTER_DATE='%ci' GIT_AUTHOR_DATE='%ai' git commit --amend --no-edit --reset-author [pull] rebase = merges [merge] ff = false autoStash = true conflictStyle = diff3 ; TODO: `zdiff3` removes edge common lines but is too new? ; conflictStyle = zdiff3 [am] threeWay = true [rerere] enabled = true [diff] renames = copies algorithm = histogram [url "ssh://git@"] pushInsteadOf = https:// [protocol] allow = never [protocol "file"] allow = always [protocol "ssh"] allow = always [protocol "https"] allow = always [transfer] fsckObjects = true [fsck] zeroPaddedFilemode = warn badTimezone = warn [receive "fsck"] zeroPaddedFilemode = warn badTimezone = warn [fetch "fsck"] zeroPaddedFilemode = warn badTimezone = warn [notes] rewriteRef = refs/notes/commits [format] notes = true [status] showStash = true submoduleSummary = true [log] ; abbrevCommit = true decorate = short [log] date = relative [blame] date = relative [log] graphColors = \ BrightRed, \ BrightGreen, \ BrightYellow, \ BrightBlue, \ BrightMagenta, \ BrightCyan [diff] wsErrorHighlight = all colorMoved = zebra colorMovedWS = ignore-space-change [color "diff"] ; TODO: Harmonize with `vimdiff`? ; TODO: Use `dim` and remove `Bright`? Terminal support? commit = BrightYellow meta = BrightBlue frag = Blue func = Blue context = BrightWhite contextBold = BrightWhite reverse contextDimmed = White reverse old = BrightRed oldBold = BrightRed reverse oldDimmed = Red reverse new = BrightGreen newBold = BrightGreen reverse newDimmed = Green reverse oldMoved = BrightMagenta oldMovedDimmed = BrightMagenta oldMovedAlternative = Magenta oldMovedAlternativeDimmed = Magenta newMoved = BrightCyan newMovedDimmed = BrightCyan newMovedAlternative = Cyan newMovedAlternativeDimmed = Cyan whitespace = BrightRed reverse [color "diff-highlight"] ; TODO: Harmonize with `vimdiff`? oldNormal = BrightRed newNormal = BrightGreen oldHighlight = BrightRed Red newHighlight = BrightGreen Green [blame] ; coloring = repeatedLines coloring = highlightRecent [color "blame"] ; repeatedLines = White highlightRecent = \ 245, 2 years ago, \ 246, 1 year ago, \ 247, 6 months ago, \ 248, 3 months ago, \ 249, 1 months ago, \ 250, 2 weeks ago, \ 251, 1 weeks ago, \ 252, 5 days ago, \ 253, 2 days ago, \ 254, 1 days ago, \ 255 [absorb] ; https://github.com/tummychow/git-absorb maxStack = 100 ; [instaweb] ; ; TODO: There seems to be bugs with both `local` and `python` in ; ; `git-instaweb`! Look at, fix, and sumbit patches for them. ; local = true ; httpd = python [pretty] compact = tformat:%C(BrightYellow)%h%C(auto) %C(BrightWhite)%s%C(auto)%d columnars = tformat:%C(BrightYellow)%h%x20%C(BrightMagenta)%>(13,trunc)%ar%x20%C(BrightBlue)%<(15,trunc)%aN%x20%C(BrightWhite)%s%C(auto)%d columnart = tformat:%C(BrightYellow)%h%x09%C(BrightMagenta)%>(1 )%ar%x09%C(BrightBlue)%<(1 )%aN%x09%C(BrightWhite)%s%C(auto)%d patch = format:%C(BrightYellow)commit %h%C(auto)%d%n%C(BrightYellow)Author: %aN <%aE>%n%C(BrightYellow)Date: %ad%n%n%C(Yellow)%s%n [alias] ; All. ; TODO: `eval` the supplied command (if any), so that one can use pipes ; and other shell features? That would require one to type `git all git ; ` (i.e. repeat `git` twice) for Git commands though. ; Actually, borrow an idea from git aliases themselves? If the command ; starts with `!` then strip it and do `eval "$@"`, otherwise do `git ; "$@"`? all = "!f() { : ; \ [ -t 1 ] && tty=true; \ git config --get-colorbool color.all && color_all=always; \ git config --get-colorbool color.ui && color_ui=always; \ find -L . -type d -name '*.git' -prune \ | sed 's#^\\./\\|/\\.git$##g' \ | LC_ALL=C sort \ | awk '{ \ for (parent in parents) \ if (index($0, parent \"/\") == 1) \ next; \ parents[$0]; \ print; \ }' \ | { \ if [ $# -eq 0 ]; \ then \ if [ \"$tty\" ]; \ then \ tree -n --fromfile; \ else \ cat; \ fi; \ else \ if [ $color_all ]; \ then \ get_color() { git -C \"$path\" config --get-color \"$@\"; }; \ color_reset=$(get_color '' reset); \ color_all_header=$(get_color color.all.header \"BrightWhite White\"); \ fi; \ while read -r path; \ do \ output=$(git -C \"$path\" -c color.ui=$color_ui \"$@\" 2>&1); \ [ \"$output\" ] || continue; \ printf '%s# %s%s\\n%s\\n\\n' \ \"$color_all_header\" \ \"$path\" \ \"$color_reset\" \ \"$output\"; \ done; \ fi; \ } \ | eval \"LESS=${LESS-FRX} $(git var GIT_PAGER)\"; \ }; f" ; Tree. ; This could have been basically `git ls-files | tree --fromfile` but ; `--fromfile` doesn't look at the filesystem at all and misses ; permission bits for coloring. Instead, we use `tree`'s `-P` and `-I` ; even though they can only match on file basenames, so this solution ; is quite brittle. Also, `git ls-files` quotes "unusual" charactes, ; even with `git -c core.quotePath=false`. The only way around that is ; to pass `-z` but of course that uses null separators, which shell ; command substitution doesn't handle. So to convert the nulls to ; newlines we have to thread the return code out through extra file ; descriptors as a string.. Unix is elegant, right? Yes, I know about ; `-o pipefail`, that POSIX is too new for me :) It mostly works. ; Actually, fuck it, it turns out `tree`'s `-P` and `-I` are not ; anchored, even though they support `*` but no anchoring mechanism, so ; we get even more false positives than expected, so we do without the ; absolutely correct coloring for now. tree = "!f() { : git ls-files ; \ git config --get-colorbool color.tree && color_tree=always; \ files=\"$( \ ((( \ (git ls-files -z \"$@\"; echo $? >&3) | sed 's/\\x00/\\n/g' >&4 \ ) 3>&1) | exit $(cat)) 4>&1 \ )\" || return; \ printf '%s\\n' \"$files\" \ | tree -a -n ${color_tree+-C} --fromfile; \ return; \ dirs=\"$( \ printf '%s\\n' \"$files\" \ | sed -n 's#\\([^/]\\+\\)/.*#\\1#p' \ | sort -u \ | paste -sd '|' \ )\"; \ pattern=\"$( \ printf '%s\\n' \"$files\" \ | sed 's#/#\\n#g' \ | sort -u \ | paste -sd '|' \ )\"; \ ignore=\"$( \ find . \\! -name '.' -type d -prune \ | sed 's#^./##' \ | grep -Ev \"$dirs\" \ | paste -sd '|' \ )\"; \ tree -a -n ${color_tree+-C} \ --matchdirs \ --prune \ -P \"$pattern\" \ -I \"$ignore\"; \ }; f" ; Clone user repo ; `git clone-user-repo */$user/$repo` => ; `git clone */$user/$repo $user/repo` clone-user-repo ="!f() { : git clone ; \ url() { shift $(($#-1)); echo \"$1\"; }; \ url=\"$(url \"$@\")\"; \ url=\"${url%/}\"; \ repo=\"${url##*/}\"; \ user=\"${url%/*}\"; \ user=\"${user##*/}\"; \ git clone \"$@\" \"$user/$repo\"; \ }; f" ; Users. users = "!f() { : git log ; \ git log --pretty=full \"$@\" \ | sed -n 's/^\\(Author\\|Commit\\): \\(.*\\)/\\2/p' \ | LC_ALL=C sort -u; \ }; f" ; Browse. browse ="!f() { : ; \ [ $# != 0 ] || set -- $(git remote); \ for remote in \"$@\"; \ do \ url=\"$(git remote get-url \"$remote\")\"; \ printf '%s: %s\\n' \"$remote\" \"$url\"; \ { [ $(command -v xdg-open) ] && xdg-open \"$url\"; } || \ { [ $(command -v open) ] && open \"$url\"; } || \ { [ $(command -v start) ] && start \"$url\"; } || \ true; \ done; \ }; f" ; Refdiff. refdiff = "!f() { : git diff ; \ git config --get-colorbool color.diff && color_diff=always; \ git reflog --pretty='format:%h: %gs' \ | awk -F': ' '$2~/(commit|rebase).*\\((amend|finish)\\)/{print $1}' \ | while read -r ref; \ do \ git -c color.diff=$color_diff show --no-patch $ref; \ echo; \ git -c color.diff=$color_diff diff \"$@\" $ref HEAD; \ echo; \ done \ | eval \"LESS=${LESS-FRX} $(git var GIT_PAGER)\"; \ }; f" ; Reset user. reset-user = "!f() { : git filter-branch ; \ name=\"$1\"; shift; \ email=\"$1\"; shift; \ git filter-branch --env-filter \" \ GIT_AUTHOR_NAME=\\\"$name\\\"; \ GIT_AUTHOR_EMAIL=\\\"$email\\\"; \ GIT_COMMITTER_NAME=\\\"$name\\\"; \ GIT_COMMITTER_EMAIL=\\\"$email\\\"; \ GIT_COMMITTER_DATE=\\\"\\$GIT_AUTHOR_DATE\\\"; \ \" \"$@\" ; \ }; f" ; Reset date. reset-date = "!f() { : git filter-branch ; \ git filter-branch --env-filter ' \ sleep 1; \ date=\"$(date --iso-8601=s)\"; \ GIT_AUTHOR_DATE=\"$date\"; \ GIT_COMMITTER_DATE=\"$date\"; \ ' \"$@\" ; \ }; f" ; Log. ; TODO: Add `--no-merges` and `--merges` (or `--first-parent`) aliases? ; They fit well with the workflow of my personal projects. ; TODO: If would be cool to add like a `=> ${u}` to the decoration to ; also show the tracking branch if any. ; TODO: Add `--shortstat` info? ; ; TODO: Can we do nicer (Unicode) graphs? ; - l = "!f() { : git log ; \ git config --get-colorbool color.diff && color_diff=always; \ git -c color.diff=$color_diff log --graph --pretty=columnart \"$@\" \ | sed -E 's/^([^\\t]+\\t[^\\t,]+)(,.+)? ago(.*\\t.*)$/\\1\\3/' \ | sed -E 's/^(.*) +(.*[0-9a-f]{7}.*\\t)/\\1\\t\\2/' \ | sed -E 's/ *$//' \ | column -t -o ' ' -s \"$(printf '\\t')\" \ | eval \"LESS=${LESS-FRX} $(git var GIT_PAGER)\"; \ }; f" lb = log --topo-order --graph --pretty=compact --simplify-by-decoration ; `git-show-tree` from `git-extras` is similar. ls = log --topo-order --graph --pretty=compact ll = log --topo-order --graph --pretty=columnars lp = log --topo-order --patch --pretty=patch --find-copies-harder --irreversible-delete lpw = lp --color-words='[_[:alnum:]]+|[^[:space:]]' lpww = lp --color-words='.' la = l --all lba = lb --all lsa = ls --all lla = ll --all lpa = lp --all lpwa = lpw --all lpwwa = lpww --all ; Status. s = status ss = status --short sb = status --short --branch sa = s --ignored ssa = ss --ignored sba = sb --ignored ; Diff. d = diff --find-copies-harder --irreversible-delete du = diff --find-copies-harder --irreversible-delete @{upstream} dp = diff --find-copies-harder --irreversible-delete @{push} dc = d --cached duc = du --cached dpc = dp --cached dw = d --color-words='[_[:alnum:]]+|[^[:space:]]' duw = du --color-words='[_[:alnum:]]+|[^[:space:]]' dpw = dp --color-words='[_[:alnum:]]+|[^[:space:]]' dcw = dc --color-words='[_[:alnum:]]+|[^[:space:]]' ducw = duc --color-words='[_[:alnum:]]+|[^[:space:]]' dpcw = dpc --color-words='[_[:alnum:]]+|[^[:space:]]' dww = d --color-words='.' duww = du --color-words='.' dpww = dp --color-words='.' dcww = dc --color-words='.' ducww = duc --color-words='.' dpcww = dpc --color-words='.' ; Add. au = add -u aa = add -A ; Commit. c = commit ca = commit --amend ; Rebase. ri = rebase -i --rebase-merges ro = rebase -i --rebase-merges --root rr = rebase --continue ; Fetch. f = fetch ; Push. p = push pf = push --force-with-lease ; Clean ignored files (requires either `-f`, `-i` or `-n`). x = clean -Xd ; Contains. ; contains = name-rev --name-only contains = tag --contains ; contains = branch --contains ; contains = describe --contains