Last active
June 25, 2025 23:21
-
-
Save mej/14b9534212a37d4cbee91880d12fa6fe to your computer and use it in GitHub Desktop.
mej's .gitconfig
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ### -*- Mode: conf-toml; fill-column: 80; comment-auto-fill-only-comments: t; tab-width: 4; eval: (local-set-key "\C-i" 'indent-according-to-mode) -*- | |
| ################################################################################ | |
| # Git Configuration | |
| # | |
| # Michael Jennings <[email protected]> | |
| # 15 Mar 2013 | |
| # | |
| # Evolved over time and cobbled together from innumerable sources. | |
| # | |
| ################################################################################ | |
| ### Global User (i.e., Identity) Settings | |
| # Anyone grabbing and customizing this file will need to change ALL of these! | |
| # And don't forget to use the *long* GPG key ID for safety. | |
| [user] | |
| name = Michael Jennings | |
| #email = [email protected] | |
| #email = [email protected] | |
| email = [email protected] | |
| signingkey = A95EBD0D160CA591 | |
| ### Git Subcommand Aliases and JIT-Functions | |
| # These are in sections by topic (roughly) and kept alphabetized within each | |
| # section (roughly). (Occasionally my OCD-powered organizational and | |
| # grammatical pedantry is superceded by functional similarity.) | |
| # | |
| # These should work as-is, though some do rely on content later in the file | |
| # (e.g., the "hist" format for log output used by the "hist" alias). And | |
| # references to my GPG key ID, obviously, won't work for you; otherwise, the | |
| # vast majority of them should work just fine, either one-by-one or en masse. | |
| [alias] | |
| ############################################################################################################################### | |
| ### Basics | |
| bi = bisect | |
| co = checkout # RCS, CVS, SVN...and less typing! | |
| #cp = cherry-pick -x # "CherryPick" (w/hash by default) | |
| c-p = cherry-pick # Alt. to above due to "cp" conflict | |
| cpx = cherry-pick -x # "CherryPick-X" (log orig commit) | |
| cpa = cherry-pick --abort # Abort the c-p seq and reset | |
| cpc = cherry-pick --continue # Resume cherry-pick after conflict | |
| cpq = cherry-pick --quit # Same as abort w/o reset | |
| fa = fetch --all # "Fetch All," obviously. | |
| fap = fa -p # "Fetch All and Prune" | |
| fat = fa --tags # "Fetch All Tags" | |
| fatp = fa -Pt # "Fetch All Tags and Prune" CAUTION! | |
| faa = fap -P # "Fetch All and prune All the things!" | |
| ff = merge --ff-only # "FastForward" or DIE! | |
| noff = merge --no-ff # NO FastForward, even if possible | |
| mc = merge --no-ff --log # Force a "MergeCommit" (like GitHub) | |
| up = pull origin # Analogous to "cvs up" or "svn up" | |
| pullup = pull upstream # PULL the latest UPstream code | |
| get = clone --recurse-submodules # This one is self-explanatory... | |
| sl = shortlog -e # "ShortLog" (with author e-mails) | |
| stat = status | |
| ustat = status -uno # Same as "stat" but skip untracked | |
| fstat = ustat --ignored=no --ignore-submodules=all # Fast STAT | |
| fast = fstat # Going for "fast stat" even FASTer | |
| sw = switch # "co" old & busted, "SW" new hotness | |
| swc = switch -c # Same as "cob"/"co -b" but switchier | |
| fpush = push --force # Force-push for non-fast-forwards | |
| npush = push --dry-run # "-n push" - don't send the objs! | |
| tpush = push --tags # Tags aren't pushed by default... | |
| ftpush = push --force --tags # Combine the 2 above | |
| upush = push --set-upstream # Set push target as "upstream" repo | |
| # The particulars of staging and unstaging are easy to forget or mistype, | |
| # so aliases to the rescue! | |
| stage = add | |
| pstage = addi # Partial STAGE (i.e., interactively) | |
| unstage = restore -S # -S/--staged restores HEAD -> index | |
| # Use refspecs, without or with the leading '+', to push branches+tags | |
| apush = "!set -x;_gf() { git push $(git remote show) refs/heads/*:refs/heads/* refs/tags/*:refs/tags/*; }; _gf" | |
| fapush = '!_gf() { git push $(git remote show) +refs/heads/*:refs/heads/* +refs/tags/*:refs/tags/* "$@"; }; _gf' | |
| # Basics - Simple Stuff | |
| vvar = '!_gf() { if test $# -eq 0; then exec git var -l; else exec git var "$@"; fi; }; _gf' | |
| ### Extra-short shortcuts | |
| a = add | |
| b = branch | |
| c = config | |
| d = diff | |
| f = fetch | |
| g = grep | |
| h = help | |
| i = init | |
| #j = | |
| k = "!gitk --all &" # "git k" == "gitk" because typos. | |
| l = log | |
| m = merge | |
| #n = | |
| #o = | |
| p = push | |
| q = quiltimport | |
| r = rebase | |
| s = fstat | |
| t = tag | |
| #u = | |
| #v = # Need something a bit more clever here because `git-var` isn't. | |
| v = vvar | |
| w = worktree | |
| ############################################################################################################################### | |
| ### Configuration data access | |
| c-e = config --edit | |
| c-g = config --get | |
| c-s = config --set | |
| c-u = config --unset | |
| c-ua = config --unset-all | |
| # I think these are safe, but comment out if not. | |
| ce = config --edit | |
| cg = config --get | |
| cs = config --set | |
| cu = config --unset | |
| cua = config --unset-all | |
| # Everything else... | |
| c-a = config --add | |
| c-ga = config --get-all | |
| c-gb = config --get-colorbool | |
| c-gc = config --get-color | |
| c-gcb = c-gb | |
| c-gr = config --get-regexp | |
| c-gu = config --get-urlmatch | |
| c-mv = config --rename-section | |
| c-rm = config --remove-section | |
| c-ls = config --list | |
| c-lsv = config --list --show-origin --show-scope | |
| c-lsz = config --list --null | |
| c-lsn = config --list --name-only | |
| ############################################################################################################################### | |
| ### Cloning and Committing | |
| cl = clone # ...duh... | |
| clr = clone --recurse-submodules # Same as "get" but more obvious? | |
| ### Commit-related aliases | |
| amend = commit --amend # Modify last commit (also see below) | |
| ca = commit --amend -C @ # Amend, preserving log message | |
| caa = commit -a --amend -C @ # "ca" but with auto-add/auto-rm | |
| cae = commit --amend -c @ # Amend, edit previous log message | |
| caae = commit -a --amend -c @ # "cae" but with auto-add/auto-rm | |
| ci = commit # "CheckIn" (a la CVS, SVN) | |
| cia = commit -a # "ci" with automatic "git add" | |
| nci = commit --dry-run # "NoCheckIn" (or, think "rsync -n") | |
| cis = commit -S # "CheckInSigned" (user.signingkey) | |
| sci = commit -S # "SignedCheckIn" (user.signingkey) | |
| dco = commit --signoff # Commit with DCO (Signed-off-by:) | |
| lsu = ls-files -u # "LS Unmerged" (conflicted) files | |
| isync = add -A # "Index Sync" rm/adds (like mzsync) | |
| addf = add -f # ADD+Force | |
| fadd = addf # Force-ADD | |
| addi = add -fi # ADD Interactively | |
| iadd = addi # Interactive ADD | |
| addp = add -fp # ADD Patch hunks (item #5 in "add -i") | |
| padd = addp # Patch ADD | |
| ############################################################################################################################### | |
| ### Porcelains | |
| # These aliases, not unlike their common command-line option, are mainly | |
| # for purposes of automation, either in scripts or in one-liners. | |
| porcstat = status --porcelain # Parsable file/dir states | |
| statporc = porcstat | |
| po-stat = porcstat | |
| po-s = porcstat | |
| procstat = porcstat # Common typos for the win! | |
| # One more of these, because reasons. | |
| sss = status --porcelain # Status for Scripts & Stuff | |
| ############################################################################################################################### | |
| ### Pushing and Pulling | |
| # Sync (pull-then-push) all shared branches or tags to remote(s) | |
| # Origin: sync branches, sync tags, or force-push branches | |
| sync = !git pull && git push origin : && : | |
| tsync = !git pull && git push origin --tags && : | |
| syncf = !git pull && git push origin +: && : | |
| # Same as above but to both origin and "bb" (usually Bitbucket) | |
| bbsync = !git pull && git push origin : && git push bb : && : | |
| bbtsync = !git pull && git push origin --tags && git push bb --tags && : | |
| bbsyncf = !git pull && git push origin +: && git push bb +: && : | |
| ############################################################################################################################### | |
| ### Dealing with Remotes | |
| re = remote # Just a shortcut | |
| rea = remote add # REmote Add | |
| real = remote add -f --tags # REmote Add, then Load (fetch) | |
| rebr = remote set-branches # REmote set-BRanches | |
| rebra = remote set-branches --add # ^- Same + Add | |
| regu = remote get-url # REmote Get-Url | |
| rels = remote -v # REmote LiSt | |
| rels-stale = remote prune --dry-run # REmote LiSt STALE refs | |
| relss = remote prune --dry-run # REmote LiSt STALE refs | |
| relsf = remotes-fetch # REmote LiSt, Fetch-able only | |
| relsp = remotes-push # REmote LiSt, Push-able only | |
| remv = remote rename # REmote MoVe (rename) | |
| rep = remote prune # REmote Prune | |
| rerm = remote remove # REmote ReMove | |
| res = remote show # REmote Show | |
| resu = remote set-url # REmote Set-Url | |
| resup = remote set-url --push # REmote Set-Url for Push | |
| reup = remote update # REmote UPdate | |
| # Shortcuts for some of the `remotes-*` multi-remote ops (below) | |
| re-f = remotes-fetch | |
| re-p = remotes-push | |
| ### FIXME: Prefer `re`* aliases? mdo = remotes-do-a-few # Multi-remote DO | |
| redaf = remotes-do-a-few | |
| red1 = remotes-do-one | |
| redl = remotes-do-list | |
| re-do1 = remotes-do-one | |
| re-doaf = remotes-do-a-few | |
| # See above for the implementation | |
| foreach-remote = remotes-do-all | |
| fere = foreach-remote | |
| ### FIXME: Should some portion of these move into Bash/mejsh? Some of these are a wee bit gnarly as one-liners.... | |
| ### Utility functions for running commands on remote(s) | |
| # remotes-fetch returns a list of remotes that are fetch-able (should be all of them...); conditional is currently ":" (true always). | |
| remotes-fetch = "!_gf() { local C L R U; while read R U C; do if test "$C" = '(push)'; then continue; elif : ; then echo "$R"; : L+=" $R"; fi; done < <(git remote -v); }; _gf" | |
| # remotes-push returns a list of remotes that are push-able; at present, that means it's not named "upstream" and the URL isn't `no_push`. | |
| remotes-push = "!_gf() { local C L R U; while read R U C; do if test "$C" = '(fetch)' -o "$R" = 'upstream' -o "$U" = 'no_push' ; then continue; else echo "$R"; fi; done < <(git remote -v); }; _gf" | |
| # remotes-do-one executes a single command on a single remote, after some checking and decorating. | |
| remotes-do-one = "!_gf() { local C=\"$1\" R=\"$2\"; shift 2 ; printf '\\e[5;100m[===]\\e[0m \\e[1;97;40m[ %s ]\\e[0m \\e[5;100m[===]\\e[0m\\n' \"git $C${1:+ $*}: $R\" ; exec git $C $R \"$@\"; }; _gf" | |
| # remotes-do-list takes a whitespace-delimited list of remotes as $1 and the command to be run as $2, then everything else. | |
| remotes-do-list = "!_gf() { local R S=\"$1\" C=\"$2\"; shift 2; for R in $S ; do git remotes-do-one \"$C\" \"$R\" \"$@\"; done; }; _gf" | |
| # remotes-do-a-few pulls args off the command line until it hits `--` or an empty string; | |
| # then it calls remotes-do-list with all those initial args stuffed into a single arg ("$1") | |
| remotes-do-a-few = "!_gf() { local C=\"$1\" L=''; shift; while test -n \"$1\" -a \"$1\" != \"--\"; do L=\"$L $1\"; shift; done; exec git remotes-do-list \"${L:1}\" \"$C\" \"${@:2}\"; }; _gf" | |
| # remotes-do-all just invokes `git remotes-do-list` and inserts a list of all remotes' names as the 1st argument | |
| remotes-do-all = "!_gf() { exec git remotes-do-list \"$(git remotes-fetch)\" \"$@\"; }; _gf" | |
| # remotes-do-all-push is identical to "do-all" except that only remotes with "push" URLs are included | |
| remotes-do-all-push = "!_gf() { exec git remotes-do-list \"$(git remotes-push)\" \"$@\"; }; _gf" | |
| # These use "remotes-do-a-few" rather than "remotes-do-list" just because. | |
| remotes-moo-all = "!_gf() { exec git remotes-do-a-few $(git remotes-fetch) -- \"$@\"; }; _gf" | |
| remotes-moo-push-all = "!_gf() { exec git remotes-do-a-few $(git remotes-push) -- \"$@\"; }; _gf" | |
| # Push with different settings to one or more remotes (or all remotes); "t" means tags, "f" means to force-push) | |
| pushall = remotes-do-all-push push | |
| tpushall = remotes-do-all-push tpush | |
| apushall = remotes-do-all-push apush | |
| fpushall = remotes-do-all-push fpush | |
| ftpushall = remotes-do-all-push ftpush | |
| fapushall = remotes-do-all-push fapush | |
| npushall = remotes-do-all-push npush | |
| # The commands above do all push-able remotes; these next 4 take a user-supplied list of remotes as arguments terminated by an | |
| # argument of either `--` or `''`. "t"/"f" same as above; "m" means "multi-remote;" "n" means "dry-run" (usually `-n` flag). | |
| mpush = remotes-do-a-few push # Multi-remote PUSH | |
| mnpush = remotes-do-a-few npush # Multi-remote NPUSH (i.e., a dry-run push) | |
| fmpush = remotes-do-a-few fpush # Multi-remote FPUSH | |
| fmnpush = remotes-do-a-few fnpush # Multi-remote FNPUSH (dry-run for a forced push) | |
| # Push shortcuts specific to NHC | |
| ppush = push ghp | |
| pfpush = fpush ghp | |
| lpush = push lanl | |
| lfpush = fpush lanl | |
| lppush = remotes-do-a-few push ghp lanl -- | |
| lpfpush = remotes-do-a-few fpush ghp lanl -- | |
| ############################################################################################################################### | |
| ### Branching and Tagging | |
| br = branch # Just a shortcut | |
| cob = checkout -b # Make+CheckOut Branch ("co -b") | |
| #swc = switch -c # Equivalent with switch (set above) | |
| swC = switch -C # Same as "cob"/"swc" but forced | |
| brco = checkout --track # "cob" w/tracking setup (normal case) | |
| brdesc = branch --edit-desc -- # Opens branch description in editor | |
| brget = branch --show-current # BRanch GET name | |
| brls = branch --list -vv # BRanch LiSting + 2*verbose | |
| brlsa = branch -a --list -vv # "brls" for local+remote branches | |
| brlsr = branch -r --list -vv # "brls" for remote branches only | |
| brsetup = branch -u # BRanch SET UPstream | |
| bru = branch -u # BR set Upstream (same, but shorter) | |
| fbr = branch -f # Force BRanch (reset if exists) | |
| fcob = checkout -B # Force-COB (like forcing "cob" above) | |
| brmv = branch -m # BRanch MoVe (branch move/rename) | |
| fbrmv = branch -M # "brmv" even if new name exists | |
| brrm = branch -d # BRanch ReMove | |
| fbrrm = branch -D # "brrm" even if not merged upstream | |
| # The following 5 aliases break standard ordering and are thus deprecated. | |
| mkbr = checkout -B # MaKe BRanch (br -f, then co) | |
| mvbr = branch -m # MoVe BRanch (branch move/rename) | |
| fmvbr = branch -M # "mvbr" even if new name exists | |
| rmbr = branch -d # ReMove BRanch | |
| frmbr = branch -D # "rmbr" even if not merged upstream | |
| # CheckOut with Tracking or with Tracking + Branchname (either order) | |
| cot = checkout -t | |
| cobt = "!_gf() { exec git checkout -b \"${1}\" -t \"${@:2}\"; }; _gf" | |
| cotb = "!_gf() { exec git checkout -t \"${1}\" -b \"${@:2}\"; }; _gf" | |
| # Create developer or bugfix branches with "standard" naming | |
| bdev = "!_gf() { exec git checkout -b \"$(id -un)/dev/${1}\" \"${@:2}\"; }; _gf" | |
| bfix = "!_gf() { exec git checkout -b \"$(id -un)/fix/${1}\" \"${@:2}\"; }; _gf" | |
| # These *should* do the exact same thing as the 2 above, but for now... | |
| #devb = bdev | |
| #fixb = bfix | |
| devb = "!_gf() { exec git checkout -b \"dev/$(id -un)/${1}\" \"${@:2}\"; }; _gf" | |
| fixb = "!_gf() { exec git checkout -b \"fix/$(id -un)/${1}\" \"${@:2}\"; }; _gf" | |
| # brhist ("BRanch HISTory") is defined in "shortlog" section below | |
| tls = tag -l # Tag LiSting | |
| tll = tag -n -l # Tag Long Listing (w/annotation) | |
| tmv = tag -f # Tag MoVe (i.e., --force); not good! | |
| trm = tag -d # Tag ReMove (delete) | |
| atag = tag -af # "AnnotatedTAG" w/force to move | |
| stag = tag -s # "SignedTAG" | |
| # List tags showing commit hash, tag value, tag msg, commit msg for each | |
| tags = for-each-ref --sort='-authordate' --sort='-*authordate' --format='%(if)%(*objectname)%(then)%(color:yellow)%(*objectname:short)%(color:reset) %(align:40,left)%(color:yellow bold)(%(align:15,left)"%(refname:short)" %(end)%(align:25,left)"%(subject)")%(end)%(end)%(color:reset) %(align:80,left)%(*subject)%(end)%(else)%(align:80,left)%(color:yellow)%(objectname:short)%(color:reset) %(refname:short)%(end) %(align:80,left)%(subject)%(end)%(end)' refs/tags | |
| # Previous (tag subjects not aligned): for-each-ref --sort='-authordate' --sort='-*authordate' --format='%(if)%(*objectname)%(then)%(color:yellow)%(*objectname:short)%(color:reset) %(align:40,left)%(color:yellow bold)(tag:%(refname:short) %(subject))%(end)%(color:reset) %(align:80,left)%(*subject)%(end)%(else)%(align:80,left)%(color:yellow)%(objectname:short)%(color:reset) %(refname:short)%(end) %(align:80,left)%(subject)%(end)%(end)' refs/tags | |
| ############################################################################################################################### | |
| ### Diffs and Patches | |
| dw = diff --word-diff # Word-based diff | |
| # "dc" shows the diff for a specific commit; "dcw" is word-based "dc" | |
| dc = "!_gf() { git diff ${1:-HEAD}^..${1:-HEAD} \"${@:2}\"; }; _gf" | |
| dcw = "!_gf() { git diff --color-words ${1:-HEAD}^..${1:-HEAD} \"${@:2}\"; }; _gf" | |
| # Same as the previous 2 for those (me) with pre-existing muscle memory | |
| cdiff = dc | |
| cwdiff = dcw | |
| di = diff -p --staged # Diff against Index (def. HEAD) | |
| diw = diff -p --staged --word-diff # Word-based "di" | |
| diffstat = diff --stat # Generate diffstat output | |
| dirstat = diff --dirstat # Generate dirstat output | |
| dds = dirstat --stat # Both of the above ("Dir+DiffStats") | |
| dsp = dds -p # All of the above ("DDS w/Patch") | |
| idiff = diff -p --staged # "IndexDiff" (same as "di") | |
| ncdiff = diff --color=never # "Non-Colored DIFF" for patch creation | |
| dnc = ncdiff # Alternative ("Diff w/No Color") | |
| ncidiff = nc idiff # "No-Color" idiff | |
| dinc = nc idiff # "DI" from above but with No Color. | |
| dcnc = nc cdiff # "DC" from above with No Color | |
| dcwnc = nc cwdiff # "DCW" from above with No Color | |
| ### Patch Generation | |
| # Usage: git gp "pkgname-version" "Reason for patch" [ other-args ] | |
| gp = "!_gf() { local DS=\"$(date \"+%Y%m%d\")\" N=\"${1:-$(basename ${PWD})}\" PN R=\"${2:+${2// /_}}\"; R=\"${R:-wip-${DS}}\"; PN=\"${N,,}${R:+-${R,,}}\"; git dnc \"${@:3}\" > \"${PN}.patch\"; diff-highlight \"${PN}.patch\" 2>/dev/null; }; _gf" | |
| # gp = "!~/bin/git-gp" | |
| ### Archive generation (tar up anything in `git status` output) | |
| ad-delta = "!_gf() { awk '{print $2}' < <(git status --porcelain); }; _gf" | |
| archdiff = "!_gf() { exec tar --one-file-system --xattrs --acls --selinux -Hpax -Pachpv -f \"$@\" -T <(git ad-delta); }; _gf" | |
| diffarch = archdiff | |
| archd = archdiff | |
| darch = archdiff | |
| ### Some other diff-based aliases | |
| df = diff-files -p # Diff Files | |
| dfw = diff-files -p --word-diff # Word-based "df" | |
| dt = diff-tree # Abbreviation for "diff-tree" | |
| ### Diff Highlighting | |
| # Uses external `diff-highlight` script, originally from Git, that highlights smaller, more specific changes | |
| dhl = "!_gf() { export GIT_PAGER=\"${GIT_PAGER:-$(git config --get core.pager)}\" ; git \"${1:-diff}\" \"${@:2}\" | diff-highlight | ${GIT_PAGER} ; }; _gf" | |
| # I do this constantly, so I made a quicker shortcut: | |
| #dhdl = "!_gf() { export GIT_PAGER=\"${GIT_PAGER:-$(git config --get core.pager)}\" ; git dl \"$@\" | diff-highlight | ${GIT_PAGER} ; }; _gf" | |
| #dhd = "!_gf() { export GIT_PAGER=\"${GIT_PAGER:-$(git config --get core.pager)}\" ; git diff --color=never \"$@\" | diff-highlight | ${GIT_PAGER} ; }; _gf" | |
| dhdl = dhl dl # Diff-Highlight DiffLog | |
| dhll = dhl dllast # "dllast" with highlighting | |
| ### Non-repository Diff Variants | |
| # All these are mainly just adding `fs` to the beginning | |
| fsd = diff --no-index # FileSystem-only Diff | |
| fsdw = fsd --color-words # FSD Word-based | |
| fsdnc = fsd --color=never # FSD with No Color | |
| ############################################################################################################################### | |
| ### History and Logs | |
| # Commit history, 1 per line, with graph. "BackWard"/"Reverse" for oldest first. | |
| hist = log --graph --decorate --format=hist | |
| histbw = log --graph --decorate --format=hist --reverse | |
| rhist = log --graph --decorate --format=hist --reverse | |
| hista = log --graph --decorate --format=hist --all | |
| ha = hista | |
| histabw = log --graph --decorate --format=hist --all --reverse | |
| rhista = log --graph --decorate --format=hist --all --reverse | |
| # Different ways of spelling "log" with formats under "[pretty]" | |
| la = log --graph --decorate --format=logall --all | |
| ll = log --format=fuller | |
| lla = log --format=fuller --all | |
| ls = log --format=listing | |
| lsa = log --format=listing --all | |
| refhist = log -g --pretty=oneline # REFerence HISTory (reflog, def. HEAD) | |
| ### Displaying commit history with diffs ("difflogs") | |
| # "difflog" and its shorter form "dl" show commit log & diffs together | |
| difflog = log -p --stat --pretty=difflog | |
| dl = difflog | |
| # "dlbw" ("DiffLog BackWard") shows difflog in reverse (oldest first) | |
| dlbw = difflog --reverse | |
| # "dlw" ("DiffLog Words") shows the difflog with word-based diffs | |
| dlw = difflog --color-words | |
| # "dlwbw" simply combines the last 2 into 1 | |
| dlwbw = dlw --reverse | |
| last = log -p -1 @ # "dl" for latest commit only (@ = HEAD) | |
| dllast = dl -1 @ # "dl" for latest commit only (@ = HEAD) | |
| ### "shortlog" displays summaries, branches, release notes | |
| slog = shortlog -e # "ShortLog" (with author e-mails) | |
| # "RELeaseLOG" shows commits by author; for release notes, etc. | |
| rellog = shortlog -en --format='* [%h] %s' -w'79,4,6' | |
| mrlog = shortlog -en --pretty=mrlog -w'0,2,12' | |
| # "BRanch HISTory" shows inter-branch deltas (symmetric differencing) | |
| brhist = shortlog --cherry-mark --left-right --no-merges | |
| headhist = shortlog --walk-reflogs # HEAD HISTory (from reflog) | |
| histf = shortlog --cherry # "HISTory of Forks" | |
| walkrl = shortlog --walk-reflogs # "WALK RefLogs" | |
| who = shortlog -se # Summarize commit counts by author | |
| # "RefLogGREP" | |
| rlgrep = "!_gf() { git shortlog --walk-reflogs --grep-reflog=\"${1}\" \"${@:2}\"; }; _gf" | |
| ############################################################################################################################### | |
| ### Restore | |
| # `git-restore` is a relatively new Git subcommand used for snarfing content from some other source | |
| # into the working tree or the index | |
| # Pulls content into the worktree by default (or with -W) or index (-S) | |
| rest = restore # RESTore worktree from another source | |
| irest = restore -S # Index RESTore (--staged) | |
| trest = restore -W # workTree RESTore (--worktree) | |
| itrest = restore -SW # Both of the above simultaneously | |
| # Same 4 aliases, this time with a different source specified (-s/--source) | |
| rests = restore -s # RESTore worktree from Source | |
| irests = restore -Ss # Index RESTore from Source | |
| trests = restore -Ws # workTree RESTore from Source | |
| itrests = restore -SWs # Both of the above simultaneously | |
| arrest = restore -W . # All-Repo RESTore from HEAD | |
| ############################################################################################################################### | |
| ### Clean | |
| # Working directory cleanup (to remove build products, etc.) aliases below distinguish among 3 "tiers" of tidying: | |
| # - "git clean" uses the `git-clean` defaults, so it only removes untracked files throughout the tree | |
| # - "git clear" goes a step further, recursing *into* untracked directories to remove their contents (and them) | |
| # - "git wipe" is the harshest of the 3, removing ignored files and dirs as well as untracked ones | |
| # Be careful, especially with `git wipe`; removed items cannot be recovered. Consider doing a dry-run first (`nclean`, | |
| # `nclear`, and `nwipe`) to review what would be removed, or use interactive mode (`iclean`/`iclear`/`iwipe`) to refine your | |
| # selection by hand (and no action will be taken until you're done). | |
| # | |
| # NOTE: By default, `git-clean` will not remove anything unless the `-f`/`--force` flag is given. This has always seemed | |
| # kinda silly to me -- why would you be running `git clean` if you didn't want it to clean?! -- so that behavior is | |
| # disabled in the `[clean]` section below, so don't rely on that safety net unless you restore it yourself!! | |
| # | |
| clear = clean -d # Nuke all untracked files & dirs | |
| wipe = clean -xd # Nuke untracked+ignored files & dirs | |
| nclean = clean -n # Dry-run of "clean" | |
| nclear = clear -n # Dry-run of "clear" | |
| nwipe = wipe -n # Dry-run of "wipe" | |
| iclean = clean -i # Interactive "clean" | |
| iclear = clear -i # Interactive "clear" | |
| iwipe = wipe -i # Interactive "wipe" | |
| cleanig = clean -X # Clean *only* ignored files/dirs | |
| igclean = cleanig | |
| ncleanig = cleanig -n # Dry-run of "cleanig" | |
| ignclean = ncleanig | |
| # These should be easy to remember too...because dry cleaning...it's punny! | |
| dryclean = clean -n # These should be self-explanatory | |
| dryclear = clear -n | |
| drywipe = wipe -n | |
| # Even punnier! "dry" -> "dri" for -i/--interactive! | |
| driclean = clean -in # These should be self-explanatory | |
| driclear = clear -in | |
| driwipe = wipe -in | |
| ############################################################################################################################### | |
| ### Searching commit/delta history | |
| # "Pickaxe" refers to searching for commits that change lines matching | |
| # a given regexp (-G) or for commits that change the number of | |
| # occurrences of a specified string (-S) or extended regexp | |
| # (--pickaxe-regex -S). By default, the only diffs that are shown are | |
| # for files that triggered the match, but --pickaxe-all shows the entire | |
| # changeset. The aliases below use "pa" for "PickAxe" and "apa" for | |
| # "AllPickAxe" (i.e., --pickaxe-all). "grep" (normal regex grep), | |
| # "fgrep" (grep -F), and "egrep" (grep -E) are used as mnemonics for | |
| # each of the behaviors described above, respectively, each with ("apa") | |
| # and without ("pa") the --pickaxe-all flag. Do note, however, that the | |
| # semantics are subtly different between "-S<regex> --pickaxe-regex" and | |
| # "-G<regex>" as described in git-log(1) and gitdiffcore(7). | |
| apaegrep = log -p --stat --pickaxe-all --pickaxe-regex -S | |
| apafgrep = log -p --stat --pickaxe-all -S | |
| apagrep = log -p --stat --pickaxe-all -G | |
| paegrep = log -p --stat --pickaxe-regex -S | |
| pafgrep = log -p --stat -S | |
| pagrep = log -p --stat -G | |
| pickaxe = log -p --stat -G | |
| ############################################################################################################################### | |
| ### Rewriting history by reordering, squashing, fixing, and/or undoing commits | |
| histedit = rebase --interactive # Pretty self-explanatory, I think. | |
| hreset = reset --hard # "HardRESET" is also pretty obvious. | |
| sreset = reset --soft # "SoftRESET" is too... | |
| rbi = rebase --interactive # ...as is "ReBaseInteractively." | |
| # Actions taken *during* a rebase | |
| rba = rebase --abort # ReBase Abort | |
| rbc = rebase --continue # ReBase Continue | |
| rbe = rebase --edit-todo | |
| rbp = rebase --show-current-patch | |
| rbq = rebase --quit # ReBase Quit | |
| rbs = rebase --skip # ReBase Skip | |
| # FIXME: Rename section to Merging and Rebasing, and clean this up. | |
| mra = merge --abort # MeRge Abort | |
| mrc = merge --continue # MeRge Continue | |
| mrq = merge --quit # MeRge Quit (abort without reset) | |
| unadd = reset -- # Reset by itself undoes "git add" | |
| # Interactive un-add; if 1st arg isn't a path, must be a "<tree-ish>" | |
| unaddi = "!_gf() { if [ -e \"${1}\" ]; then exec git reset -p -- \"$@\" ; else exec git reset -p \"${1}\" -- \"${@:2}\" ; fi; }; _gf" | |
| # Back up HEAD for the current branch by some number of commits | |
| backout = "!_gf() { if [ -n \"${1}\" -a -z \"${1//[0-9]}\" ]; then exec git reset --hard HEAD~${1} \"${@:2}\" ; else exec git reset --hard \"${@}\" ; fi; }; _gf" | |
| bk = backout | |
| # "UNdo CommIts" or "UNdoCIs" - Revert HEAD back to <commit> but leave changes staged in index. | |
| #unci = reset --soft | |
| unci = "!_gf() { if [ -n \"${1}\" -a -z \"${1//[0-9]}\" ]; then exec git reset --soft HEAD~${1} \"${@:2}\" ; else exec git reset --soft \"${@}\" ; fi; }; _gf" | |
| # "ReMove CommIts"/"ReMoveCIs" - Revert HEAD and index back to <commit> but leave changes in working tree. | |
| #rmci = reset --mixed | |
| rmci = "!_gf() { if [ -n \"${1}\" -a -z \"${1//[0-9]}\" ]; then exec git reset --mixed HEAD~${1} \"${@:2}\" ; else exec git reset --mixed \"${@}\" ; fi; }; _gf" | |
| # "ReWriteCommIts" or "ReWriteCIs" - refactor the last <num> commits (`@` == `HEAD`) | |
| rwci = "!_gf() { local b=$(git rev-parse --abbrev-ref @ 2>/dev/null) ; if [ -n \"${1}\" -a -z \"${1//[0-9]}\" ]; then exec git rbi @~${1} @ \"${@:2}\" ; else exec git rbi \"${@}\" ; fi; }; _gf" | |
| ############################################################################################################################### | |
| ### Worktrees, Subtrees, and Submodules | |
| # Abbreviated aliases for common git-worktree tasks | |
| wt = worktree | |
| wta = worktree add | |
| wtalk = worktree add --lock | |
| wtal = wtalk | |
| wtls = worktree list | |
| wtlsv = worktree list -v | |
| wtlsp = worktree list --porcelain | |
| wtlsz = worktree list --porcelain -z | |
| wtmv = worktree move | |
| wtp = worktree prune | |
| wtrm = worktree remove | |
| wtrep = worktree repair | |
| wtfix = wtrep | |
| wtfsck = wtrep | |
| wtlk = worktree lock | |
| wtulk = worktree unlock | |
| wtconfig = config --worktree | |
| wtcfg = wtconfig | |
| wtconf = wtconfig | |
| ### Working with subtrees and submodules | |
| # Base shortcuts | |
| st = subtree | |
| sm = submodule | |
| # Subtree add/update | |
| sta = "!_gf() { git subtree add --prefix \"${2}\" \"${1}\" master --squash; }; _gf" | |
| stu = "!_gf() { git subtree pull --prefix \"${2}\" \"${1}\" master --squash; }; _gf" | |
| # Submodule add (TODO: Do "git add" for <name> and .gitmodules and "git commit") | |
| #sma = "!_gf() { git submodule add \"$@\"; }; _gf" | |
| sma = submodule add | |
| smi = submodule init | |
| smd = submodule deinit | |
| smfe = submodule foreach | |
| smsb = submodule set-branch | |
| smsu = submodule set-url | |
| smstat = submodule status | |
| smsync = submodule sync --recursive | |
| smup = submodule update --init --recursive --jobs 4 | |
| foreach-sm = submodule foreach | |
| fesm = foreach-sm | |
| ############################################################################################################################### | |
| ### Assorted generalized goop | |
| # No Color - Generic wrapper tool to disable color | |
| nc = "!_gf() { export NEVER=never ; exec git -c color.pager=false --config-env=color.{advice,blame,branch,decorate,diff,grep,interactive,push,remote,showbranch,status,transport,ui}'=NEVER' \"$@\"; }; _gf" | |
| # Stash if needed, then fetch refs, fetch tags, fast-forward merge, and if stash was done, pop stashed changes. If something | |
| # goes wrong, launch a clean Bash shell with no fancy prompts, no history, and a custom prompt for making repairs. | |
| sync-up = "!_gf() { local -i RC=0 STASH_POP=0; if test -n \"$(git status -uno --porcelain --ignore-submodules=all)\"; then STASH_POP=1; git stash; fi; git fetch --all --recurse-submodules=yes && git fetch --all --tags && git merge --ff; RC=$?; if (( STASH_POP && !RC )); then git stash pop; RC=$?; fi; return ${RC}; }; _gf" | |
| sup = sync-up | |
| # Basically equivalent to "sync-up" above but includes some special handling for the Bash history file. | |
| sync-up-home = "!_gf() { local STASH_POP=0 ; if test -n \"$(git status -uno --porcelain --ignore-submodules=all)\" ; then STASH_POP=1 ; git stash ; fi ; git fetch --all --recurse-submodules=yes && git fetch --all --tags && git merge --ff ; test $STASH_POP -eq 1 && (git stash pop || (git restore \"$(readlink -f \"${HISTFILE}\")\" && git stash pop || /bin/bash --noprofile --rcfile <( echo 'export GIT_PS1= PS1=\"[no-hist-sync] \\u@\\h \\w ${PCHAR:->}> \" PROMPT_COMMAND= HISTFILE=' ) -i); }; _gf" | |
| shup = sync-up-home | |
| # Switch to a local tracking branch and sync it up with the corresponding remote's equivalent branch (e.g., "dev" <- "origin/dev"). | |
| # The remote-tracking branch in the local repo is updated via "fetch," after which the local branch gets fast-forwarded to match. | |
| sync-tracking-branch = "!_gf() { local OB='' SP='' TB=\"${1}\"; local -i RC=0 STASH_POP=0; OB=\"$(git rev-parse --abbrev-ref 2>/dev/null)\"; SP=\"$(git status -uno --porcelain --ignore-submodules=all)\"; STASH_POP=$(( ${#SP} > 0 ? 1 : 0 )); (( STASH_POP )) && git stash; git switch "${TB}" && git fetch --all --recurse-submodules=yes && git fetch --all --tags && git merge --ff; RC=$?; if (( STASH_POP && !RC )); then git stash pop; RC=$?; fi; if (( RC != 0 )); then /bin/bash --noprofile --rcfile <( echo 'export GIT_PS1= PS1=\"[no-hist-sync] \\u@\\h \\w ${PCHAR:->}> \" PROMPT_COMMAND= HISTFILE=' ) -i; RC=$?; fi; return ${RC}; }; _gf" | |
| #ffb ### FIXME: WTF was this going to be, "fetch fuckinbranch" or something??! | |
| tbsync = sync-tracking-branch | |
| ############################################################################################################################### | |
| ### Configuration for git-core, git-branch, etc. | |
| [core] | |
| abbrev = 8 | |
| # These are normally "true" but must be "false" on FAT, some NTFS, et al. | |
| filemode = true | |
| symlinks = true | |
| #protectNTFS = true # Would this be good or bad?? | |
| # True uses native Win API whenever possible | |
| ignorecygwinFStricks = true | |
| # Should auto-set itself to true when needed, but ONLY at time | |
| # of initialization or clone! | |
| ignorecase = false | |
| sharedrepository = group # Preserve group permissions | |
| gitproxy = lanl-gitproxy-socat # Requires external script | |
| pager = less -+S -FRXi -z-1 | |
| logAllRefUpdates = always | |
| whitespace = blank-at-eol,space-before-tab,blank-at-eof,tabwidth=4 | |
| # "Alternative" line-ending settings for non-UNIX platforms...maybe? | |
| #eol = crlf | |
| #autoCRLF = true | |
| #safeCRLF = true | |
| # Git-native permissions control; use only 1 of the values shown | |
| #sharedrepository = group/true | all/world/everybody | umask/false | 0nnn | |
| [branch] | |
| # For *any* newly created branch, set it to rebase on update (i.e., pull) | |
| autosetuprebase = always | |
| sort = -authordate | |
| [checkout] | |
| guess = true | |
| defaultRemote = origin | |
| [clean] | |
| # WARNING: This changes the "git clean" command to NOT require -f/--force! | |
| requireForce = false | |
| [commit] | |
| # Always remove comment lines & extra whitespace, see git-commit(1) | |
| cleanup = strip | |
| # Includes HEAD..index diff in commit log message template | |
| verbose = true | |
| [diff] | |
| tool = meld | |
| prompt = false | |
| mnemonicprefix = true | |
| dirstat = lines,cumulative,10 | |
| [fetch] | |
| parallel = 4 | |
| prune = true | |
| pruneTags = false | |
| recurseSubmodules = true | |
| [gc] | |
| pruneExpire = 6.months.ago | |
| reflogExpire = never | |
| reflogExpireUnreachable = 3.months.ago | |
| rerereResolved = 1.year.ago | |
| rerereUnresolved = 9.months.ago | |
| [grep] | |
| lineNumber = true | |
| patternType = perl | |
| extendedRegexp = true | |
| threads = 0 | |
| fallbackToNoIndex = true | |
| [i18n] | |
| # NOTE: Most users will want to use the default of UTF-8! | |
| commitencoding = ISO-8859-1 | |
| logoutputencoding = ISO-8859-1 | |
| [merge] | |
| conflictstyle = diff3 | |
| log = true | |
| # tool = diffuse | |
| tool = meld | |
| defaultToUpstream = true | |
| [pull] | |
| # Rebase local commits onto the fetched branch rather than merging | |
| rebase = true | |
| [push] | |
| # Push the currently checked-out branch if none is specified | |
| default = current | |
| followTags = true | |
| recurseSubmodules = check | |
| [rebase] | |
| autoSquash = true | |
| autoStash = true | |
| stat = true | |
| ### REuse REcorded REsolution | |
| [rerere] | |
| autoUpdate = true | |
| enabled = true | |
| [stash] | |
| showPatch = true | |
| showStat = true | |
| [status] | |
| short = false | |
| branch = true | |
| aheadBehind = true | |
| showStash = true | |
| showUntrackedFiles = normal | |
| submoduleSummary = true | |
| [submodule] | |
| recurse = true | |
| fetchJobs = 4 | |
| [tag] | |
| sort = -authordate | |
| [interactive] | |
| singlekey = true | |
| [color] | |
| status = always | |
| diff = always | |
| log = always | |
| ui = auto | |
| branch = auto | |
| grep = always | |
| decorate = always | |
| interactive = auto | |
| pager = true | |
| showbranch = auto | |
| [pretty] | |
| # Text format for "git hist" alias - colorized 1-line history with graph | |
| hist = tformat:%C(auto)%h%C(reset)[%C(auto,cyan)%as%C(auto)]%d %C(auto,bold white)<%ae>%C(reset) %C(auto)%s%C(reset) | |
| # For "git la" ("LogAll") - Decorated commit history w/graph for HEAD+refs/* | |
| logall = tformat:%C(auto)%h%Creset%C(auto)%d%Creset %s (%C(auto,cyan)%cr%Creset) by %C(auto,bold white)%aN%Creset | |
| # For "git ls" ("LiSting") - One-line commit history only, no graph | |
| listing = tformat:%C(auto)%h%Creset%C(auto)%d%Creset %s (%C(auto,cyan)%cr%Creset) by %C(auto,bold white)%aN%Creset | |
| # Format for "git difflog" (or "dl") along with a few similar variations | |
| # Shows detailed commit history with log messages and diffs | |
| difflog = tformat:Commit: %C(auto)%h%Creset%C(auto)%d%Creset from %C(auto)%p%Creset%nAuthor: %C(auto,bold yellow)%aN <%aE>%Creset %C(auto,cyan)(%ad)%Creset%nCommit: %C(auto,bold yellow)%cN <%cE>%Creset %C(auto,cyan)(%cd)%Creset%n%n%C(auto,bold white)%w(76,4,4)%s%Creset%n%n%w(76,4,4)%b%n | |
| mrlog = tformat:- [%h] %s | |
| [format] | |
| attach = true | |
| ##cc = [email protected] | |
| coverletter = true | |
| ##headers = "Organization: Los Alamos National Laboratory\n" | |
| numbered = true | |
| pretty = medium | |
| signature = | |
| signoff = true | |
| subjectprefix = PATCH | |
| suffix = .patch | |
| thread = deep | |
| to = [email protected] | |
| [sendemail] | |
| smtpencryption = tls | |
| smtpserver = smtp.gmail.com | |
| smtpserverport = 587 | |
| smtpuser = [email protected] | |
| thread = false | |
| confirm = auto | |
| [tar] | |
| umask = 0022 | |
| [help] | |
| autocorrect = 20 | |
| [url "git+ssh://[email protected]/"] | |
| insteadOf = gh: | |
| [url "git+ssh://[email protected]/mej/"] | |
| insteadOf = ghm: | |
| [url "git+ssh://[email protected]/hpc/"] | |
| insteadOf = ghpc: | |
| [url "git+ssh://[email protected]/kraken-hpc/"] | |
| insteadOf = ghk: | |
| [url "git+ssh://[email protected]/"] | |
| insteadOf = bb: | |
| [url "git+ssh://[email protected]/mej0/"] | |
| insteadOf = bbm: | |
| [url "git+ssh://[email protected]/"] | |
| insteadOf = lgl: | |
| [url "git+ssh://[email protected]/mej/"] | |
| insteadOf = lglm: | |
| [url "git+ssh://[email protected]:10122/"] | |
| insteadOf = hgl: | |
| [url "git+ssh://[email protected]:10122/mej/"] | |
| insteadOf = hglm: | |
| [url "git+ssh://[email protected]:10122/platforms/"] | |
| insteadOf = hglp: | |
| [url "git+ssh://[email protected]:10022/"] | |
| insteadOf = cmgl: | |
| [url "git+ssh://[email protected]:10022/mej/"] | |
| insteadOf = cmglm: | |
| [gui] | |
| editor = emacs-w32 --no-desktop | |
| [cola] | |
| textwidth = 132 | |
| tabwidth = 4 | |
| [remote "origin"] | |
| tagOpt = --tags |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment