book
  • README
  • cheatsheet
    • bash
      • builtin
      • syntactic sugar
      • cmd
      • havefun
    • text-processing
      • awk
      • sed
      • html
      • json
      • regex
      • unicode
    • osx
    • curl
    • tricky
    • widget
    • proxy
    • colors
    • math
    • media
    • ssl
      • keystore
      • verification
      • server
      • client
      • tricky
    • windows
      • powershell
      • choco
      • wsl
      • wt
      • shortcut
      • clsid
      • env
      • shell:folder
  • vim
    • nvim
    • install
    • color
    • plugins
      • usage
      • other plugins
      • deprecated
    • tricky
    • viml
    • windows
    • troubleshooting
  • devops
    • admin tools
    • ssh
    • git
      • config
      • alias
      • submodule
      • eol
      • example
      • gerrit
        • gerrit API
      • github
      • troubleshooting
      • tricky
      • statistics
    • pre-commit
    • release-tools
    • tmux
      • cheatsheet
    • ansible
    • vault
    • artifactory
      • api
      • cli
      • aql
      • nginx cert
    • klocwork
      • kwadmin
      • kwserver
      • api
      • q&a
    • elk
    • mongodb
    • android
    • mobile
  • jenkins
    • config
      • windows
    • appearance
    • troubleshooting
    • jenkinsfile
      • utility
      • parallel
      • build
      • envvar
      • properties
      • trigger
      • node
    • script
      • job
      • build
      • stage
      • agent
      • security & authorization
      • exception
      • monitor
      • tricky
    • api
      • blueocean
    • cli
    • plugins
      • kubernetes
      • docker
      • shared-libs
      • lockable-resource
      • ansicolor
      • badge
      • groovy-postbuild
      • simple-theme
      • customizable-header
      • artifactory
      • jira-steps
      • job-dsl
      • build-timeline
      • crumbIssuer
      • coverage
      • uno-choice
      • tricky
  • virtualization
    • kubernetes
      • init
        • kubespray
        • kubeadm
          • environment
          • crio v1.30.4
          • docker v1.15.3
          • HA
        • addons
        • etcd
      • kubectl
        • pod
        • deploy
        • replicasets
        • namespace
        • secrets
      • node
      • certificates
      • events
      • kubeconfig
      • kubelet
      • troubleshooting
      • cheatsheet
      • auth
      • api
      • tools
        • monitor
        • helm
        • network
        • minikube
    • docker
      • run & exec
      • voume
      • remove
      • show info
      • dockerfile
      • dockerd
      • tricky
      • troubleshooting
      • windows
    • crio
    • podman
  • ai
    • prompt
  • osx
    • apps
      • init
      • brew
    • defaults
    • system
    • network
    • script
    • tricky
  • linux
    • devenv
    • util
      • time & date
      • output formatting
      • params
      • tricky
    • nutshell
    • disk
    • network
    • troubleshooting
    • system
      • apt/yum/snap
      • authorization
      • apps
      • x11
    • ubuntu
      • systemctl
      • x
    • rpi
  • programming
    • groovy
    • python
      • config
      • basic
      • list
      • pip
      • q&a
    • others
    • archive
      • angular
      • maven
      • mysql
        • installation
        • logs
      • ruby
        • rubyInstallationQ&A
  • tools
    • fonts
    • html & css
    • Jira & Confluence
    • node & npm
      • gitbook
      • hexo
      • github.page
      • code themes
    • app
      • microsoft office
      • vscode
      • virtualbox
      • iterm2
      • browser
      • skype
      • teamviewer
      • others
  • quotes
  • english
Powered by GitBook
On this page
  • tricky
  • trailers
  • scripts
  • git message
  • refspec
  • others

Was this helpful?

  1. devops
  2. git

tricky

PrevioustroubleshootingNextstatistics

Last updated 1 month ago

Was this helpful?

tricky

references:

hidden feature

$ git var GIT_COMMITTER_IDENT
marslo <marslo.jiao@gmail.com> 1719963678 -0700

$ git var -l

quick edit gitconfig

$ git config --edit --global

# quick repalce config
$ git config --global --replace-all core.pager cat

create git patch

$ git diff --no-color HEAD^..HEAD > <name>.patch

# or
$ git format-patch HEAD^^           # create 3 patch files automatically
$ git format-patch -1 <revision>    # create 1 patch file only

get current branch

$ git branch
  sandbox/marslo
* master
  • $ git branch --show-current
    
    # or
    $ git branch --show
    
    # or
    $ git branch | sed -ne 's:^\*\s*\(.*\)$:\1:p'
    master
  • $ git symbolic-ref --short HEAD
    master
    
    $ git symbolic-ref HEAD
    refs/heads/master
  • $ git name-rev --name-only HEAD
    remotes/origin/master
  • describe

    $ git describe --contains --all HEAD
    master

get previous branch

get previous branch name

$ git rev-parse --symbolic-full-name @{-1}
refs/heads/sandbox/marslo/291

or

$ git describe --all $(git rev-parse @{-1})
heads/sandbox/marslo/291
$ git checkout -
  • or

    $ git checkout @{-1}

quick diff with previous branch

$ git diff ..@{-1}

# or
$ git diff @..@{-1}

# or
$ git diff HEAD..@{-1}

quick push to current branch

  • @

@ alone is a shortcut for HEAD.

references:

$ git push origin @

# or
$ git push origin HEAD
$ git add --all -u --renormalize .
  • or ignore the warning

    $ git config --global core.safecrlf false
$ for c in {0..10}; do
    echo "$c" >> squash.txt
    git add squash.txt
    git commit -m "add '${c}' to squash.txt"
done

revision

the first revision

$ git rev-list --max-parents=0 HEAD

git commit

git path

get absolute root path

$ git rev-parse --show-toplevel

get relative root path

$ git rev-parse --show-cdup

get absolute root path inside submodules

$ git rev-parse --show-superproject-working-tree

get .git path

$ git rev-parse --git-dir

inside the work tree or not

$ git rev-parse --is-inside-work-tree

.gitattributes

reference:

$ rm -rf .git/index
# or
$ git rm --cached -r .
# or
$ git ls-files -z | xargs -0 rm

$ git reset --hard
$ echo "* text=auto" >.gitattributes
$ git add --renormalize .
$ git status        # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"

format

$ cat .gitattributes
*             text=auto
*.sh          eol=lf
path/to/file  eol=lf

git summaries

get repo active days

$ git log --pretty='format: %ai' $1 |
      cut -d ' ' -f 2 |
      sort -r |
      uniq |
      awk '{ sum += 1 } END {print sum}'

get commit count

  • since particular commit

    $ git log --oneline <hash-id> |
          wc -l |
          tr -d ' '
    635
  • since the initial commit

    $ git log --oneline |
          wc -l |
          tr -d ' '
    780

get all files count in the repo

$ git ls-files | wc -l | tr -d ' '

get contributors

$ git shortlog -n -s -e
   110   marslo <marslo.jiao@gmail.com>
    31   marslo <marslo@xxx.com>
$ git shortlog -n -s -e |
      awk ' {
        sum += $1
        if ($NF in emails) {
            emails[$NF] += $1
        } else {
            email = $NF
            emails[email] = $1
            # set commits/email to empty
            $1=$NF=""
            sub(/^[[:space:]]+/, "", $0)
            sub(/[[:space:]]+$/, "", $0)
            name = $0
            if (name in names) {
                # when the same name is associated with existed email,
                # merge the previous email into the later one.
                emails[email] += emails[names[name]]
                emails[names[name]] = 0
            }
            names[name] = email
        }
      } END {
        for (name in names) {
            email = names[name]
            printf "%6d\t%s\n", emails[email], name
      }
    }'
   141  marslo

format the author

$ git shortlog -n -s -e | awk '
  { args[NR] = $0; sum += $0 }
  END {
    for (i = 1; i <= NR; ++i) {
      printf "%s♪%2.1f%%\n", args[i], 100 * args[i] / sum
    }
  }
  ' | column -t -s♪ | sed "s/\\\x09/\t/g"
   110  marslo <marslo.jiao@gmail.com>  78.0%
    31  marslo <marslo@xxx.com>         22.0%

show diff file only

$ git log --numstat --pretty="%H" --author=marslo HEAD~3..HEAD
9fdb297ba0d2d51975e91d2b7e40fb5e96be4f5f

8       1       docs/artifactory/artifactory.md
095ec79c89d98831c0a485f55011bf81c6f712ad

49      11      docs/linux/disk.md
5       1       docs/osx/util.md
f15a40c8dea2927db54570268aca4203cd50a416

1       0       docs/SUMMARY.md
-       -       docs/screenshot/tools/ms/outlook-keychain-1.png
81      0       docs/tools/ms.md

repo age

$ git log --reverse --pretty=oneline --format="%ar" |
      head -n 1 |
      LC_ALL=C sed 's/ago//'
4 months

who-am-i

[!NOTE|label:references:]

# show default credential
$ echo -e 'protocol=https\nhost=github.com' | git credential fill
protocol=https
host=github.com
username=marslo
password=gho_jzuA**************************1VRqXz

# show antoher credential with specific subpath
$ echo -e 'protocol=https\nhost=github.com/mdevapraba' | git credential fill
protocol=https
host=github.com/mdevapraba
username=marslojiao-mvl
password=ghp_ppHq*************************g1PXSvr
  • reject the cached

    $ echo -e 'protocol=https\nhost=github.com' | git credential reject
$ git bisect start
$ git bisect bad                 # current commit is bad
$ git bisect good <commit-hash>  # a known good commit
$ git show <commit-hash>:path/to/file
$ echo "node_modules/" >> .gitignore
$ git rm -r --cached node_modules/
$ git commit -m "Update .gitignore"

trailers

[!NOTE|label:references:]

git config

[!TIP|label:tips:]

  • if trailer.sign.command is not set, the default value is git var GIT_COMMITTER_IDENT

  • if trailer.sign.key set as "Signed-off-by: ", it will impacted the git log --format=%(trailers:key=Signed-off-by:,valueonly,separator=%x2C)

$ git config --global trailer.sign.key "Signed-off-by"
$ git config --global trailer.sign.ifmissing add
$ git config --global trailer.sign.ifexists doNothing
$ git config --global trailer.sign.command "echo \"$(git config user.name) <$(git config user.email)>\""

# or
$ cat ~/.gitconfig
[trailer "sign"]
  key               = Signed-off-by
  ifmissing         = add
  ifexists          = doNothing
  command           = echo \"$(git config user.name) <$(git config user.email)>\"

generate trailers

[!NOTE|label:references:]

$ git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p'

## commit-msg.sample

# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
         sort | uniq -c | sed -e '/^[   ]*1[    ]/d')" || {
        echo >&2 Duplicate Signed-off-by lines.
        exit 1
}
  • by template

    $ cat ~/.git-template
    Signed-off-by: Your Name <your.email@example.com>
    
    $ git config commit.template ~/.git-template

commit

$ git commit --signoff
# or
$ git commit -s
  • with control

    declare signed="$(git log -n1 --format='%(trailers:key=Signed-off-by,valueonly,separator=%x2C)' | command grep -q "$(git config user.email)"; echo $?)";
    if [ 0 -eq ${signed} ]; then
      OPT='commit --amend --allow-empty';
    else
      OPT='commit --signoff --amend --allow-empty';
    fi;
  • i.e.:

    [alias]
    ### [c]ommit [a]dd [a]all
    caa         = "!f() { \
                          git add --all; \
                          declare signed=\"$(git log -n1 --format='%(trailers:key=Signed-off-by,valueonly,separator=%x2C)' | command grep -q \"$(git config user.email)\"; echo $?)\"; \
                          if [ 0 -eq ${signed} ]; then \
                            git commit --amend --no-edit --allow-empty;\
                          else \
                            git commit --signoff --amend --no-edit --allow-empty;\
                          fi; \
                        }; f \

show trailers

[!NOTE|label:references:]

$ git log -n1 --format='%(trailers:key=Signed-off-by:,valueonly,separator=%x2C)'
marslo <marslo.jiao@gmail.com>

$ git log -n1 --format='%(trailers:key=Signed-off-by:,keyonly,separator=%x2C)'
Signed-off-by

# or
$ git log -n1 --format=%B | git interpret-trailers --parse
Signed-off-by: marslo <marslo.jiao@gmail.com>
Change-Id: I3cc1cb4cfaf4300d2e7972eb39a7319e81012c65

# or
$ git log -1 --pretty=format:"%b"
Signed-off-by: marslo <marslo.jiao@gmail.com>
Change-Id: I3cc1cb4cfaf4300d2e7972eb39a7319e81012c65

# or
$ git log --pretty=format:"%b" | command grep -E "^(Signed-off-by|Co-authored-by):"

configure and format

  • Signed-off-by:

    $ git config --global trailer.sign.key 'Signed-off-by: '
    $ git log -1 --format="%(trailers:key=Signed-off-by,valueonly,separator=%x2C)"
    
    $ git log -1 --format="%(trailers:key=Signed-off-by: ,valueonly,separator=%x2C)"
    marslo <marslo.jiao@gmail.com>
  • Signed-off-by

    $ git config --global trailer.sign.key 'Signed-off-by'
    
    $ git log -1 --format="%(trailers:key=Signed-off-by: ,valueonly,separator=%x2C)"
    
    $ git log -1 --format="%(trailers:key=Signed-off-by:,valueonly,separator=%x2C)"
    marslo <marslo.jiao@gmail.com>
    $ git log -1 --format="%(trailers:key=Signed-off-by,valueonly,separator=%x2C)"
    marslo <marslo.jiao@gmail.com>

scripts

$ cat ~/.gitconfig
...
[alias]
  ua          = "!bash -c 'while read branch; do \n\
                   echo -e \"\\033[1;33m~~> ${branch}\\033[0m\" \n\
                   git fetch --all --force; \n\
                   if [ 'meta/config' == \"${branch}\" ]; then \n\
                     git fetch origin --force refs/${branch}:refs/remotes/origin/${branch} \n\
                   fi \n\
                   git rebase -v refs/remotes/origin/${branch}; \n\
                   git merge --all --progress refs/remotes/origin/${branch}; \n\
                   git remote prune origin; \n\
                   if git --no-pager config --file $(git rev-parse --show-toplevel)/.gitmodules --get-regexp url; then \n\
                     git submodule sync --recursive; \n\
                     git submodule update --init --recursive \n\
                   fi \n\
                 done < <(git rev-parse --abbrev-ref HEAD) '"
...

iGitOpt

--stat

$ git diff --stat HEAD^ HEAD
 docs/programming/groovy/groovy.md |  1 +
 docs/vim/tricky.md                | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 61 insertions(+), 21 deletions(-)
  • $ git --no-pager diff --author='marslo' --stat HEAD^ HEAD
     docs/programming/groovy/groovy.md |  1 +
     docs/vim/tricky.md                | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
     2 files changed, 61 insertions(+), 21 deletions(-)

--numstat

$ git --no-pager log --numstat --author="marslo" HEAD^..HEAD
commit c361ddf2687319f978bb4ec0069b4b996607615f (HEAD -> marslo, origin/marslo)
Author: marslo <marslo.jiao@gmail.com>
Date:   Wed Jul 28 22:21:03 2021 +0800

    add bufdo for vim

1   0   docs/programming/groovy/groovy.md
60  21  docs/vim/tricky.md
  • for total count of changes

    $ git log --numstat --pretty="%H" --author="marslo" HEAD^..HEAD |
          awk 'NF==3 {plus+=$1; minus+=$2} END {printf("+%d, -%d\n", plus, minus)}'
    +61, -21
  • $ git log HEAD^..HEAD --numstat --pretty="%H" |
          awk 'NF==3 {added+=$1; deleted+=$2} NF==1 {commit++} END {printf("total lines added: +%d\ntotal lines deleted: -%d\ntotal commits: %d\n", added, deleted, commit)}'
    total lines added: +61
    total lines deleted: -21
    total commits: 1
  • $ git log --numstat --format="" HEAD^..HEAD |
          awk '{files += 1}{ins += $1}{del += $2} END{print "total: "files" files, "ins" insertions(+) "del" deletions(-)"}'
    total: 2 files, 61 insertions(+) 21 deletions(-)
    [alias]
    summary = "!git log --numstat --format=\"\" \"$@\" | awk '{files += 1}{ins += $1}{del += $2} END{print \"total: \"files\" files, \"ins\" insertions(+) \"del\" deletions(-)\"}' #"
$ git diff --shortstat HEAD^..HEAD
 2 files changed, 61 insertions(+), 21 deletions(-)
  • $ git diff  $(git log -5 --pretty=format:"%h" | tail -1) --shortstat
     7 files changed, 253 insertions(+), 24 deletions(-)

hook

[!NOTE|label:references:]

  • commit-msg for signed-off-by

    #!/bin/sh
    
    NAME=$(git config user.name)
    EMAIL=$(git config user.email)
    
    if [ -z "$NAME" ]; then
      echo "empty git config user.name"
      exit 1
    fi
    
    if [ -z "$EMAIL" ]; then
      echo "empty git config user.email"
      exit 1
    fi
    
    git interpret-trailers --if-exists doNothing --trailer \
        "Signed-off-by: $NAME <$EMAIL>" \
        --in-place "$1"
  • commit-msg for change-id

    #!/bin/sh
    # From Gerrit Code Review 2.6
    #
    # Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
    #
    # Copyright (C) 2009 The Android Open Source Project
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    # http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    
    unset GREP_OPTIONS
    
    CHANGE_ID_AFTER="Bug|Issue"
    MSG="$1"
    
    # Check for, and add if missing, a unique Change-Id
    #
    add_ChangeId() {
      clean_message=`sed -e '
      /^diff --git a\/.*/{
      s///
      q
      }
      /^Signed-off-by:/d
      /^#/d
      ' "$MSG" | git stripspace`
      if test -z "$clean_message"; then return; fi
    
      # Does Change-Id: already exist? if so, exit (no change).
      if grep -i '^Change-Id:' "$MSG" >/dev/null; then return; fi
    
      id=`_gen_ChangeId`
      T="$MSG.tmp.$$"
      AWK=awk
      if [ -x /usr/xpg4/bin/awk ]; then
        # Solaris AWK is just too broken
        AWK=/usr/xpg4/bin/awk
      fi
    
      # How this works:
      # - parse the commit message as (textLine+ blankLine*)*
      # - assume textLine+ to be a footer until proven otherwise
      # - exception: the first block is not footer (as it is the title)
      # - read textLine+ into a variable
      # - then count blankLines
      # - once the next textLine appears, print textLine+ blankLine* as these
      # aren't footer
      # - in END, the last textLine+ block is available for footer parsing
      $AWK '
      BEGIN {
      # while we start with the assumption that textLine+
      # is a footer, the first block is not.
      isFooter = 0
      footerComment = 0
      blankLines = 0
      }
    
      # Skip lines starting with "#" without any spaces before it.
      /^#/ { next }
    
      # Skip the line starting with the diff command and everything after it,
      # up to the end of the file, assuming it is only patch data.
      # If more than one line before the diff was empty, strip all but one.
      /^diff --git a/ {
        blankLines = 0
        while (getline) { }
        next
      }
    
      # Count blank lines outside footer comments
      /^$/ && (footerComment == 0) {
        blankLines++
        next
      }
    
      # Catch footer comment
      /^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) {
        footerComment = 1
      }
    
      /]$/ && (footerComment == 1) {
        footerComment = 2
      }
    
      # We have a non-blank line after blank lines. Handle this.
      (blankLines > 0) {
        print lines
        for (i = 0; i < blankLines; i++) {
          print ""
        }
    
        lines = ""
        blankLines = 0
        isFooter = 1
        footerComment = 0
      }
    
      # Detect that the current block is not the footer
      (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) {
        isFooter = 0
      }
    
      {
        # We need this information about the current last comment line
        if (footerComment == 2) {
          footerComment = 0
        }
        if (lines != "") {
          lines = lines "\n";
        }
        lines = lines $0
      }
    
      # Footer handling:
      # If the last block is considered a footer, splice in the Change-Id at the
      # right place.
      # Look for the right place to inject Change-Id by considering
      # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first,
      # then Change-Id, then everything else (eg. Signed-off-by:).
      #
      # Otherwise just print the last block, a new line and the Change-Id as a
      # block of its own.
      END {
      unprinted = 1
      if (isFooter == 0) {
      print lines "\n"
      lines = ""
      }
      changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):"
      numlines = split(lines, footer, "\n")
      for (line = 1; line <= numlines; line++) {
      if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) {
      unprinted = 0
      print "Change-Id: I'"$id"'"
      }
      print footer[line]
      }
      if (unprinted) {
      print "Change-Id: I'"$id"'"
      }
      }' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T"
    }
    
    _gen_ChangeIdInput() {
      echo "tree `git write-tree`"
      if parent=`git rev-parse "HEAD^0" 2>/dev/null`; then
        echo "parent $parent"
      fi
      echo "author `git var GIT_AUTHOR_IDENT`"
      echo "committer `git var GIT_COMMITTER_IDENT`"
      echo
      printf '%s' "$clean_message"
    }
    _gen_ChangeId() {
      _gen_ChangeIdInput |
      git hash-object -t commit --stdin
    }
    
    add_ChangeId

git message

[!NOTE|label:references:]

TYPE
FULL NAME
SIMPLE DESCRIPTION
DESCRIPTION

build

构建系统或外部依赖项的变化

changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)

ci

CI 配置文件和脚本的更改

changes to our ci configuration files and scripts (example scopes: travis, circle, browserstack, saucelabs)

docs

documentation

仅文档修改

documentation only changes

feat

feature

新功能

a new feature

fix

bugfix

修复问题

a bug fix

perf

性能提高

a code change that improves performance

refactor

重构 (即不是新增功能, 也不是修改bug)

a code change that neither fixes a bug nor adds a feature

style

formatting

格式 (不影响代码运行的变动)

changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)

test

增加测试

adding missing tests or correcting existing tests

chore

maintain

构建过程或辅助工具的变动

changes to the build process or auxiliary tools and libraries such as documentation generation

  • sample

    docs(changelog): update changelog to beta.5
    fix(release): need to depend on latest rxjs and zone.js
    
    The version in our package.json gets copied to the one we publish, and users need the latest of these.

refspec

[!NOTE|label:references:]

others

alias

references:

show git alias

$ git --list-cmds=alias

# or
$ git config --get-regexp '^alias\.'
[alias]
  # https://stackoverflow.com/q/53841043/2940319
  ### show [g]it alia[s]
  as         = "! bash -c '''grep --no-group-separator -A1 -e \"^\\s*###\" \"$HOME\"/.marslo/.gitalias | \n\
                              awk \"END{if((NR%2))print p}!(NR%2){print\\$0p}{p=\\$0}\" | \n\
                              sed -re \"s/( =)(.*)(###)/*/g\" | \n\
                              sed -re \"s:[][]::g\" | \n\
                              awk -F* \"{printf \\\"\\033[1;33m%-20s\\033[0m » \\033[0;34m%s\\033[0m\\n\\\", \\$1, \\$2}\" | \n\
                              sort \n\
                           '''"
  • [alias]
      alias = "!sh -c '[ $# = 2 ] && git config --global alias.\"$1\" \"$2\" && exit 0 || [ $# = 1 ] && [ $1 = \"--list\" ] && git config --list | grep \"alias\\.\" | sed \"s/^alias\\.\\([^=]*\\)=\\(.*\\).*/\\1@@@@=>@@@@\\2/\" | sort | column -ts \"@@@@\" && exit 0 || echo \"usage: git alias <new alias> <original command>\\n       git alias --list\" >&2 && exit 1' -"
  • [alias]
      aliases = !git config --get-regexp ^alias\\. | sed -e s/^alias.// -e s/\\ /\\ $(printf \"\\043\")--\\>\\ / | column -t -s $(printf \"\\043\")
  • $ git config --global --get-regexp alias |
          awk -v nr=2 '{sub(/^alias\./,"")}; \
                       { printf "\033[31m%_10s\033[1;37m", $1}; \
                       {sep=FS}; \
                       {for (x=nr; x<=NF; x++) \
                       { printf "%s%s", sep, $x; }; \
                       print "\033[0;39m"}'
    • finda

      [alias]
        finda = "!grepalias() { git config --global --get-regexp alias | grep -i \"$1\" | awk -v nr=2 '{sub(/^alias\\./,\"\")};{printf \"\\033[31m%_10s\\033[1;37m\", $1};{sep=FS};{for (x=nr; x<=NF; x++) {printf \"%s%s\", sep, $x; }; print \"\\033[0;39m\"}'; }; grepalias"
  • [alias]
        show-cmd = "!f() { \
            sep="㊣" ;\
            name=${1:-alias};\
            echo -n -e '\\033[48;2;255;255;01m' ;\
            echo -n -e '\\033[38;2;255;0;01m' ;\
            echo "$name"; \
            echo -n -e '\\033[m' ;\
            git config --get-regexp ^$name\\..*$2+ | \
            cut -c 1-40 | \
            sed -e s/^$name.// \
            -e s/\\ /\\ $(printf $sep)--\\>\\ / | \
            column -t -s $(printf $sep) | \
            sort -k 1 ;\
        }; f"

ls

references:

[alias]
  ls           = "!git status -suno"
  ls-modified  = "!git status --porcelain -uno | awk 'match($1, /M/) {print $2}'"
  ls-added     = "!git status --porcelain -uno | awk 'match($1, /A/) {print $2}'"
  ls-deleted   = "!git status --porcelain -uno | awk 'match($1, /D/) {print $2}'"
  ls-renamed   = "!git status --porcelain -uno | awk 'match($1, /R/) {print $2}'"
  ls-copied    = "!git status --porcelain -uno | awk 'match($1, /C/) {print $2}'"
  ls-updated   = "!git status --porcelain -uno | awk 'match($1, /U/) {print $2}'"
  ls-staged    = "!git status --porcelain -uno | grep -P '^[MA]' | awk '{ print $2 }'"
  ls-untracked = "!git status --porcelain -uall | awk '$1 == \"??\" {print $2}'"

git alias escaping

[alias]
  # https://stackoverflow.com/a/39616600/2940319
  # Quote / unquote a sh command, converting it to / from a git alias string
  quote-string = "!read -r l; printf \\\"!; printf %s \"$l\" | sed 's/\\([\\\"]\\)/\\\\\\1/g'; printf \" #\\\"\\n\" #"
  quote-string-undo = "!read -r l; printf %s \"$l\" | sed 's/\\\\\\([\\\"]\\)/\\1/g'; printf \"\\n\" #"
$ MANWIDTH=80 MANPAGER='col -bx' git help rev-parse |
              groff -P-pa4 -Tps -mandoc -c |
              open -f -a Preview.app
# reachable objects
$ git rev-list --disk-usage --objects --all

# plus reflogs
$ git rev-list --disk-usage --objects --all --reflog

# total disk size used
$ du -c .git/objects/pack/*.pack .git/objects/??/*
# alternative to du: add up "size" and "size-pack" fields
$ git count-objects -v

# report the disk size of each branch
$ git for-each-ref --format='%(refname)' |
  while read branch; do
    size=$(git rev-list --disk-usage --objects HEAD..$branch)
    echo "$size $branch"
  done |
  sort -n

# compare the on-disk size of branches in one group of refs, excluding another
$ git rev-list --disk-usage --objects --remotes=$suspect --not --remotes=origin

[!NOTE|label:references:]

reference

or

or

or

git-tips/tips
git 的奇技淫巧
k88hudson/git-flight-rules
git飞行规则(flight rules)
firstaidgit.io
unixorn/git-extra-commands
tj/git-extras
shell tricks: one git alias to rule them all
git var
git verify-commit
branch
symbolic-ref
name-rev
checkout to previous branch
gitrevisions(7) Manual Page
remove warning: CRLF will be replaced by LF in xxx file for .gitattributes
create multiple commits
emoji
Refreshing the repository after committing .gitattributes
Please Add .gitattributes To Your Git Repository
Git tip: Add a .gitattributes file to deal with line endings
gitattributes - Defining attributes per path
Force LF eol in git repo and working copy
or
Be a Git ninja: the .gitattributes file
collection
Can I hold git credentials in environment variables?
git-tool credential
find bug with bisect
view file at specific commit
edit .gitignore after committing
git interpret-trailers
git log
git commit
Git Trailers
mmcclimon/git-slog.pl
What is the Sign Off feature in Git for?
Git magic keywords in commit messages (Signed-off-by, Co-authored-by, Fixes, ...)
Git sign off previous commits?
Git - Detect if commit is signed off
Git: How to list specific trailers (footers) in git-log format?
fetch merge all
gfall
ig.sh
for particular account
for pretty format
or
git alias
--shortstat
check for multiple commits
git提交待审核代码,报错没有change-id的解决方法
git add Signed-off-by line using format.signoff not working
* Conventional Commits
Commit Message Guidelines
AngularJS Git Commit Message Conventions
Add Choice [ chore, revert ] to question "Select the type of change you are committing" #36
10.5 Git Internals - The Refspec
putermancer/.gitconfig
List Git aliases
Shell Tricks: One Git Alias to Rule Them All
automatic documentation of gitconfig aliases using sed or awk
git config alias escaping
or
or
or
show-cmd
putermancer/.gitconfig
taxilian/.gitconfig
check help in previw.app
disk size
How is git commit sha1 formed
How is the Git hash calculated?
tricky
hidden feature
quick edit gitconfig
create git patch
get current branch
get previous branch
quick push to current branch
remove warning: CRLF will be replaced by LF in xxx file for .gitattributes
create multiple commits
revision
git commit
git path
.gitattributes
git summaries
who-am-i
find bug with bisect
view file at specific commit
edit .gitignore after committing
trailers
git config
generate trailers
show trailers
scripts
fetch merge all
gfall
iGitOpt
hook
git message
refspec
others
alias
check help in previw.app
disk size
How is git commit sha1 formed