Sign up for free to use this document yourself.
  • $ git reset HEAD^
    $ git add -p
  • Single commit/patch

    $ git --git-dir=../source_repo/.git \
    format-patch -k -1 --stdout \
    $COMMIT_SINCE | \
    git am -3 -k --committer-date-is-author-date

    where format-patch options are:

    • -k, --keep-subject Do not strip/add [PATCH] from the first line of the commit log message.
    • -1, -<n> Prepare patches from the topmost commits.
    • --stdout Print all commits to the standard output in mbox format, instead of creating a file for each one.
  • Multiple commits

    Assuming a repository like:

    [A] -> [B] -> [C] -> [D] -> [E] ...

    You can transplant it onto unrelated repository [X], to achieve something like:

    [X] -> [C] -> [D] -> [E] ...

    To do that, first, git fetch both repositories into one, then:

    git rebase B E --onto X --committer-date-is-author-date

    Source: http://stackoverflow.com/a/9091843/98528

  • Apply patch in fuzzy way

    [TODO]

    See: git help apply

    • git apply [OPTIONS] [<patch>...]
    • --recount — tries to apply changes in fuzzy way
    • --index — puts the changes into staged area too

    Does not create a commit.

  • Simpler variant, possible to quickly type by hand from memory

    $ git log --graph --oneline --decorate --all "$@"

    (old version: git log --graph --decorate --pretty=oneline --abbrev-commit --all "$@")

  • Better variant, impossible to type quickly from memory, paste it into a script

    $ git log --graph --all --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(cyan)%an%Creset' --abbrev-commit
  • If you want to revert changes made to your working copy, do this:

    git checkout .

    If you want to revert changes made to the index (i.e., that you have added), do this:

    git reset
  • git merge -Xignore-space-change
  • To create a merge like in diagram below:

    o     merge!
    |\
    | o   [snapshot]
    o     [old]
    |
    o
    |
    o     rev0

    where “snapshot” is newer than “old”, do as follows:

    git checkout old
    git merge -ssubtree snapshot -Xignore-space-change
  • git -c merge.conflictstyle=diff3 checkout -m $FILE
  • a) Find commits which add/remove lines matching a regex (i.e. search history)

    git log -G"$REGEX" -p --decorate -a
    • -p shows the actual diff, only of the files containing the change (I think)
    • --decorate is optional (shows info about tags, branches etc.)
    • -a I think makes it look into all commits on all branches. I don’t know yet how to sort the results in sensible order (e.g. by date), however.
    • alternatively, instead of -G, can use -S for simple strings, but it has slightly different semantics! It shows commits where the total count of lines matching the string changes.
  • b) Find text in current repository

    In other words, a “faster grep“:

    git grep ...

    Bonus: can be set as :grep in vim with:

    :set gp=git\ grep\ -n
  • c) Find commit by date

    git rev-list -n 1 --before="2009-07-27 13:37" master

    Source: stackoverflow

  • Initial setup, Linux [1][2]

    (unverified yet)

    The .git/info/sparse-checkout file uses patterns “similar to .gitignore” [2][3]

    git config core.sparsecheckout true
    git remote add -f origin git://...
    ## NOTE: below no whitespace between '*' and '>'
    #echo PATH/TO/SUBDIR/*> .git/info/sparse-checkout
    echo some/dir/ >> .git/info/sparse-checkout
    echo another/sub/tree >> .git/info/sparse-checkout
    git checkout BRANCHNAME
  • Existing repo, or changes [1]

    git config core.sparsecheckout true
    echo some/dir/ >> .git/info/sparse-checkout
    echo another/sub/tree >> .git/info/sparse-checkout
    git read-tree -mu HEAD
  • Disable [1]

    (unverified)

    echo '*' > .git/info/sparse-checkout
    git read-tree -mu HEAD
    git config core.sparsecheckout false
  • git show $REV:$PATH

    Since git ~1.7+, $PATH can be relative with ./path.

  • Alternatively, if the file is to be restored at its original place, a shortcut is:

    git checkout $REV $PATH

    Source: http://stackoverflow.com/a/2734035

  • git log --diff-filter=D --summary
    • git ls-tree --full-tree -r HEAD — list all tracked files already in repo (via);
    • git ls-files — list files including staged (via);
  • git commit --verbose
  • git log --pretty="format:" --name-only [RANGE...]
  • #!/bin/sh
    # git-attic [-M] [PATH] - list deleted files of Git repositories
    #
    # Use -M to not show renamed files, and other git-log options as you like.
    
    git log --raw --no-renames --date=short --format="%h %cd" "$@" |
      awk '/^[0-9a-f]/ { commit=$1; date=$2 }
           /^:/ && $5 == "D" { print date, commit "^:" $6 }' |
      git -p column

    Source: http://chneukirchen.org/blog/archive/2013/01/a-grab-bag-of-git-tricks.html

  • ORIGIN_URL=$( git --git-dir $SUBREPO/.git config --get remote.origin.url | tee /dev/stderr )
    
    git submodule add $ORIGIN_URL $SUBREPO

    Sources: man git-submodule, remote.origin.url

  • Commit:

    • HEAD^ — commit before HEAD
      • HEAD^2 — chooses other parent in merge commits
      • HEAD^^, HEAD^^^, … — grandparent of HEAD, grand-grandparent, etc.
    • HEAD~3 = HEAD^^^ = HEAD^1^1^1
    • :/"commit message regexp" — newest commit with regexp match in commit message, reachable from anywhere
      • v0.1^{/"commit message regexp"} — newest commit with regexp, reachable from v0.1
    • refs/heads/master, refs/tags/v0.1 — “fully qualified” names of: branch master, tag v0.1

    (See: git help revisions)

  • Range of commits:

    • HEAD^!HEAD^..HEAD
  • vim: reopen all files edited before crash/kill

  • vim: new buffer (pseudo-“scratch”)

    :new

    Source: vim wikia

  • vim: insert/paste current directory name

    Useful for naming Go packages. Uses the “expression register” "=.

    In normal mode:

    "=expand("%:h:t")<Enter>p

    In insert mode (equivalent but using <C-R>):

    <C-R>=expand("%:h:t")<Enter>

    For more info about %:h:t etc., see :help filename-modifiers.

    Source: [1] [2] [3]

  • Various often used stuff

  • Windows, tabs, buffers

    • [Ctrl-w], [Shift-T] — “promote” current window into a new tab
    • :tabmv -1 — move current tab 1 position to the left (similar for +1 etc.)
    • :tabcl — close current tab
    • :tabo — leave only current tab (close all others)
    • :tabdo windo e — reload all buffers in all windows in all tabs
  • Quickfix window

    • :cex system('go build ./...') — run specified command and load the result in quickfix list. If the result can be parsed using ‘errorformat’, cursor will be moved to position of first error.
      • | copen — add after above command to also show the quickfix window
    • :cn / :cp — jump to next/previous error from quickfix list
    • :ccl — close quickfix window

    [TODO] describe stuff in ‘set errorformat’

  • Registers (copy, paste, …)

    • :let @a = "foobar" — put text foobar in register a
    • :let @f = @% — put current filename in register f; can be then reopened in a different window with :e <C-R>f
  • To exclude *_test.go (and also pipe through less while keeping colours and grouping):

    ack --go $PATTERN \
      --pager='less -R' --ignore-file=match:_test.go
  • Other examples of excludes:

    --ignore-dir=_vendor
    --ignore-file=match:'\.(txt|out|log)$'
  • [Enter] [~] [.]

    Also, to break out of a nested hanged session (i.e. ssh within ssh), repeat [~] n times. E.g. for session 1 level deep:

    [Enter] [~] [~] [.]

  • Other tricks:

    [Enter][~][#] — list forwarded ports in current session

    [Enter][~][?] — list all available ~-commands

    Source: lonesysadmin.net (via)

  •  $ ssh -t -i $PRIVATE_KEY $USER@$MACHINE 'sudo -u $GUI_USER bash -c "DISPLAY=:0.0 import -window root -screen /home/$GUI_USER/foo.png" '
    [sudo] password for $USER:
    Connection to $MACHINE closed.
    1. on $LOCAL machine, pick $USER via whom the tunnel will be built
    2. if $USER has SSH login disabled, enable it temporarily:

      LOCAL$ sudo usermod --expiredate "" $USER
      LOCAL$ sudo passwd -u $USER
    3. deploy private SSH key on $REMOTE machine (e.g. as $KEY_PATH), and put the public counterpart of the key in /home/$USER/.ssh/authorized_keys on $LOCAL machine

      Note: the private key must have chmod 400

    4. setup a reverse tunnel, on $REMOTE machine:

      REMOTE$ ssh -i $KEY_PATH -o StrictHostKeyChecking=no \
              -Nf -R 16003:localhost:22 $USER@$LOCAL
    5. login via the reverse tunnel:

      LOCAL$ ssh localhost -p 16003
    6. do what you need via reverse ssh…

    7. cleanup:

      REMOTE$ rm $KEY_PATH
      REMOTE$ ps aux | grep ssh
      REMOTE$ kill ...   # kill the process from step 4

      If step 2 was done, reverse it:

      LOCAL$ sudo usermod --expiredate 1 $USER
      LOCAL$ sudo passwd -l $USER
  • On server

    If possible (root access), run an extra instance of sshd on a distinct port, with detailed logs printed to console:

    $ sudo /usr/sbin/sshd -d -p 2222

    Source: unix.stackexchange

    On client

    Run ssh with -vvv flag for detailed logs. Together with the extra server as above, this may look like:

    $ ssh -vvv -p 2222 $USER@$HOST

    Source: askubuntu

  • Best solution:

    $ ssh-keygen -E md5 -lf <( ssh-keyscan localhost 2>/dev/null )
    $ ssh-keygen -E sha256 -lf <( ssh-keyscan localhost 2>/dev/null )

    Sources: unix.stackexchange [1] [2]


    Alternative:

    $ ssh-keygen -E md5 -lf /etc/ssh/ssh_host_rsa_key.pub
    $ ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ecdsa_key.pub

    One-liner:

    ls -1 /etc/ssh/ssh_host_*.pub | join -j2 <( printf "md5\nsha256" ) - | awk '{system("ssh-keygen -E "$1" -lf "$2)}'

    same but wrapped:

    ls -1 /etc/ssh/ssh_host_*.pub |
      join -j2 <( printf "md5\nsha256" ) - |
      awk '{system("ssh-keygen -E "$1" -lf "$2)}'

    Sources:

  • For all hosts:

    $ ssh-keygen -l -f ~/.ssh/known_hosts
    $ ssh-keygen -l -f ~/.ssh/known_hosts -E md5

    For single host:

    $ ssh-keygen -l -f ~/.ssh/known_hosts -F $HOST:$PORT
    $ ssh-keygen -l -f ~/.ssh/known_hosts -F $HOST:$PORT -E md5

    Source: stackoverflow

  • Windows: ignore vendor in go test

    Powershell script [TODO: how one runs it?]:

    $GOPKG = (go list ./... ) | Out-String -stream | select-string -NotMatch vendor
    iex "go test -v $GOPKG"

    Source: golang.org/issue/15355

  • Pattern 1: poor man’s pattern-matching switch

    func ... {
      type change struct {from, to X}
      switch (change{a, b}) {
      case change{Foo, Bar}:
        ...
      }
  • Pattern 2: easy reentrant Close for goroutines

    func NewX() *X {
      x := &X{
        quit: make(chan struct{}),
      }
      go x.loop()
      return x
    }
    
    func (x *X) Close() error {
      <-x.quit
    }
    
    func (x *X) loop() {
      for {
        select {
        case x.quit<-struct{}{}:
          close(x.quit)
          return
        case y, ok := <-x.myChan:
          if !ok {
            // myChan closed, but we still have to allow x.Close()
            close(x.quit)
            return
          }
          // ... real work ...
        }
    }
  • Commands reuse

    • [Esc], [#] (or [Alt-#] or [Alt-3] or [Esc], [3]) — insert comment sign (“#”) at start of current line, then cancel the line (like Ctrl-C), saving it to history (for later fixing/completing & reuse)
    • [Alt-.] — paste last argument from previous command (press again for earlier commands)
      • [Alt-n], [Alt-.] — paste n-th argument from previous command (starting from 0)
    • [Ctrl-r], some-text — incremental search backwards through history

    Moving, editing

    • [Ctrl-a] / [Ctrl-e] — move to start/end of current line
    • [Alt-b] / [Alt-f] — move 1 word backwards/forwards
    • [Ctrl-k] — kill (delete) part of line after cursor (to line end)
    • [Shift-PgUp] / [Shift-PgDn] — scroll terminal window up/down
  • sudo netstat -l -p | grep $PORT
    • -l — show listening server sockets
    • -p — show PID/program name
    • (-W — wide: don’t truncate IP addresses)
  • $ sudo dpkg-reconfigure virtualbox-dkms
    $ sudo dpkg-reconfigure virtualbox
    $ sudo modprobe vboxdrv

    (via)

  • Login to remote server with serial port, then start serving the port:

    client$ ssh -L 3334:localhost:3334 server
    server$ sudo socat -ddd -ddd /dev/ttyS0,raw,b115200,$(cat stty-flags | sed '1,4d' | sed 's/-\([^ ]*\)/\1=0/g' | tr ' ' '\n' | grep -vE 'cmspar|iutf8|extproc' | paste -d, -s ) tcp-l:3334

    Create a local virtual serial port (will get assigned a name in /dev/pts/*) forwarded to remote one:

    client$ sudo socat -ddd -ddd pty,link=foobar,raw,echo=0 tcp:localhost:3334
  • $ curl --resolve "named-host.com:80:$IP" http://named-host.com

    Source: some stackoverflow

  • $ echo | openssl s_client -connect $HOST:443 2>/dev/null |
      openssl x509 -noout -enddate
    notAfter=...

    Source: realguess.net

  • Fingerprints for ~/.ssh/authorized_keys{,2}:

    cat ~/.ssh/authorized_keys | xargs -n1 -I% bash -c 'ssh-keygen -l -f /dev/stdin <<<"%"'

    same but wrapped:

    cat ~/.ssh/authorized_keys |
      xargs -n1 -I% bash -c 'ssh-keygen -l -f /dev/stdin <<<"%"'
  • Host fingerprints: see SSH command above

  • Any of the following should do:

    $ curl ipinfo.io/ip
    $ curl ifconfig.me
    $ curl icanhazip.com
    $ curl ident.me
    $ curl checkip.amazonaws.com

    Source: askubuntu.com

  • $ cat ... > index.html
    $ python -m SimpleHTTPServer $PORT

    Source: gist

  • WARNING: These techniques should only be used for non-merge commits. If you have a merge commit, you are better off deleting the merge and recreating it.

    If you want to perform significant work on the last commit, you can simply git reset HEAD^. This will undo the commit (peel it off) and restore the index to the state it was in before that commit, leaving the working directory with the changes uncommitted, and you can fix whatever you need to fix and try again.

    […]

  • [FIXME]

    vim -r $(find . -regex '.*/\.\(.*\.\)?sw[po]')
    # or, vim -p + 'cut'? kinda:
    vim -p $(find . -regex '.*/\.\(.*\.\)?sw[po]' | sed 's/\.[^.]*$//' )
    # maybe better:
    vim -p $(ls -1t $(find . -regex '.*/\.\(.*\.\)?sw[po]' ) | sed 's#/\.\([^/]*\)\.[^.]*$#/\1#')

    Based on: :help recovery

{"cards":[{"_id":"37ff2e2157a8f60d0300001b","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":null,"content":"## Split top commit in half\n\nMore at source: _[On undoing, fixing, or removing commits in git - A git choose-your-own-adventure!ⓡ](http://sethrobertson.github.io/GitFixUm/fixup.html)_\n\nSee also _[Post-Production Editing Using Git](http://sethrobertson.github.io/GitPostProduction/gpp.html)_ for great tutorial on `git rebase -i $EARLIER_SHA`"},{"_id":"37ff378b57a8f60d0300001c","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":"37ff2e2157a8f60d0300001b","content":" $ git reset HEAD^\n $ git add -p"},{"_id":"37ff438157a8f60d0300001f","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":"37ff378b57a8f60d0300001c","content":"> **WARNING:** These techniques should only be used for non-merge commits. If you have a merge commit, you are better off deleting the merge and recreating it.\n\n> If you want to perform significant work on the last commit, you can simply `git reset HEAD^`. This will undo the commit (peel it off) and restore the index to the state it was in before that commit, leaving the working directory with the changes uncommitted, and you can fix whatever you need to fix and try again.\n\n> [...]"},{"_id":"37ff460957a8f60d03000020","treeId":"37ff2da057a8f60d03000018","seq":1,"position":2,"parentId":null,"content":"## Transplant a patch from unrelated repository\n\nSource: http://stackoverflow.com/a/9507417/98528"},{"_id":"37ff48b857a8f60d03000021","treeId":"37ff2da057a8f60d03000018","seq":8409954,"position":1,"parentId":"37ff460957a8f60d03000020","content":"## Single commit/patch\n\n $ git --git-dir=../source_repo/.git \\\n format-patch -k -1 --stdout \\\n $COMMIT_SINCE | \\\n git am -3 -k --committer-date-is-author-date\n\nwhere `format-patch` options are:\n\n- `-k, --keep-subject` Do not strip/add [PATCH] from the first line of the commit log message.\n- `-1, -<n>` Prepare patches from the topmost <n> commits.\n- `--stdout` Print all commits to the standard output in mbox format, instead of creating a file for each one."},{"_id":"39f5cf4452acc3bc89000018","treeId":"37ff2da057a8f60d03000018","seq":5444117,"position":2,"parentId":"37ff460957a8f60d03000020","content":"## Multiple commits\n\nAssuming a repository like:\n\n [A] -> [B] -> [C] -> [D] -> [E] ...\n\nYou can transplant it onto unrelated repository `[X]`, to achieve something like:\n\n [X] -> [C] -> [D] -> [E] ...\n\nTo do that, first, `git fetch` both repositories into one, then:\n\n git rebase B E --onto X --committer-date-is-author-date\n\n_Source: http://stackoverflow.com/a/9091843/98528_"},{"_id":"5fa71cb3b7eb27769400002d","treeId":"37ff2da057a8f60d03000018","seq":5444230,"position":3,"parentId":"37ff460957a8f60d03000020","content":"## Apply patch in fuzzy way\n\n*[TODO]*\n\nSee: `git help apply`\n\n* `git apply [OPTIONS] [<patch>...]`\n* `--recount` -- tries to apply changes in fuzzy way\n* `--index` -- puts the changes into staged area too\n\nDoes *not* create a commit."},{"_id":"37ff4b0057a8f60d03000022","treeId":"37ff2da057a8f60d03000018","seq":1,"position":3,"parentId":null,"content":"## Show history using pretty ASCII-Art tree graph"},{"_id":"37ff4c9357a8f60d03000023","treeId":"37ff2da057a8f60d03000018","seq":5975599,"position":1,"parentId":"37ff4b0057a8f60d03000022","content":"## Simpler variant, possible to quickly type by hand from memory\n\n $ git log --graph --oneline --decorate --all \"$@\"\n\n<sub>(old version: `git log --graph --decorate --pretty=oneline --abbrev-commit --all \"$@\"`)</sub>\n"},{"_id":"49768fc3ad0d219571000030","treeId":"37ff2da057a8f60d03000018","seq":5975600,"position":2,"parentId":"37ff4b0057a8f60d03000022","content":"## Better variant, impossible to type quickly from memory, paste it into a script\n\n $ git log --graph --all --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(cyan)%an%Creset' --abbrev-commit"},{"_id":"37ff59c357a8f60d03000024","treeId":"37ff2da057a8f60d03000018","seq":1,"position":4,"parentId":null,"content":"## Remove local changes\n\nMore at source: _[How to revert all local changes in a GIT managed project to previous state?](http://stackoverflow.com/q/1146973/98528)_"},{"_id":"37ff5c9b57a8f60d03000025","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":"37ff59c357a8f60d03000024","content":"If you want to revert changes made to your working copy, do this:\n\n git checkout .\n\nIf you want to revert changes made to the index (i.e., that you have added), do this:\n\n git reset\n"},{"_id":"38c4e76c7518cf646f000014","treeId":"37ff2da057a8f60d03000018","seq":1,"position":4.5,"parentId":null,"content":"## Merge, ignoring whitespace\n\nSource: http://stackoverflow.com/a/9784089/98528"},{"_id":"38c4e7f27518cf646f000015","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":"38c4e76c7518cf646f000014","content":" git merge -Xignore-space-change"},{"_id":"399aaa1ccc1512596f000016","treeId":"37ff2da057a8f60d03000018","seq":1,"position":4.75,"parentId":null,"content":"## Merge a related snapshot repo\n\nSource: http://stackoverflow.com/questions/18319485/forcing-git-to-merge-add-add-conflicts#comment26892583_18319485\n"},{"_id":"399aaceecc1512596f000017","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":"399aaa1ccc1512596f000016","content":"To create a merge like in diagram below:\n\n o merge!\n |\\\n | o [snapshot]\n o [old]\n |\n o\n |\n o rev0\n\nwhere \"snapshot\" is newer than \"old\", do as follows:\n\n git checkout old\n git merge -ssubtree snapshot -Xignore-space-change\n\n"},{"_id":"5035c4248ca4ea275300003c","treeId":"37ff2da057a8f60d03000018","seq":1669185,"position":4.8125,"parentId":null,"content":"## 3-way diff of a file during merge/rebase\n\nSources: *[Git Conflict Resolution](http://tedfelix.com/software/git-conflict-resolution.html)*, *[man git](https://www.kernel.org/pub/software/scm/git/docs/git.html)*"},{"_id":"5035ca658ca4ea275300003d","treeId":"37ff2da057a8f60d03000018","seq":1669197,"position":1,"parentId":"5035c4248ca4ea275300003c","content":" git -c merge.conflictstyle=diff3 checkout -m $FILE"},{"_id":"6289b5e17d48f4419a000030","treeId":"37ff2da057a8f60d03000018","seq":5975558,"position":4.84375,"parentId":null,"content":"## Search repo/history"},{"_id":"6289b6c47d48f4419a000031","treeId":"37ff2da057a8f60d03000018","seq":5975570,"position":1,"parentId":"6289b5e17d48f4419a000030","content":"## a) Find commits which add/remove lines matching a regex (i.e. search history)\n\n git log -G\"$REGEX\" -p --decorate -a\n\n* `-p` shows the actual diff, *only of the files containing the change* (I think)\n* `--decorate` is optional (shows info about tags, branches etc.)\n* `-a` I think makes it look into all commits on all branches. I don't know yet how to sort the results in sensible order (e.g. by date), however.\n* alternatively, instead of `-G`, can use `-S` for simple strings, but it has slightly *different semantics!* It shows commits where the *total count* of lines matching the string changes."},{"_id":"6289c5f47d48f4419a000032","treeId":"37ff2da057a8f60d03000018","seq":10342623,"position":2,"parentId":"6289b5e17d48f4419a000030","content":"## b) Find text in *current* repository\n\nIn other words, a \"faster `grep`\":\n\n git grep ...\n\nBonus: can be set as `:grep` in vim with:\n\n :set gp=git\\ grep\\ -n"},{"_id":"738be2134bf64b0502000072","treeId":"37ff2da057a8f60d03000018","seq":13197653,"position":3,"parentId":"6289b5e17d48f4419a000030","content":"## c) Find commit by date\n\n git rev-list -n 1 --before=\"2009-07-27 13:37\" master\n\n*Source: [stackoverflow](https://stackoverflow.com/a/8514828/98528)*"},{"_id":"3c6e167873ff47ac71000019","treeId":"37ff2da057a8f60d03000018","seq":1,"position":4.875,"parentId":null,"content":"## Partial (\"sparse\") checkouts\n\nGit 1.7+"},{"_id":"3c6e1c3c73ff47ac7100001a","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":"3c6e167873ff47ac71000019","content":"### Initial setup, Linux <sup>[[1]](http://stackoverflow.com/a/4909267/98528)</sup><sup>[[2]](http://jasonkarns.com/blog/subdirectory-checkouts-with-git-sparse-checkout/)</sup>\n(unverified yet)\n\nThe `.git/info/sparse-checkout` file uses patterns \"similar to .gitignore\" <sup>[[2]](http://jasonkarns.com/blog/subdirectory-checkouts-with-git-sparse-checkout/)</sup><sup>[[3]](http://schacon.github.com/git/git-read-tree.html#_sparse_checkout)</sup>\n\n git config core.sparsecheckout true\n git remote add -f origin git://...\n ## NOTE: below no whitespace between '*' and '>'\n #echo PATH/TO/SUBDIR/*> .git/info/sparse-checkout\n echo some/dir/ >> .git/info/sparse-checkout\n echo another/sub/tree >> .git/info/sparse-checkout\n git checkout BRANCHNAME\n"},{"_id":"3c6e336473ff47ac7100001c","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1.5,"parentId":"3c6e167873ff47ac71000019","content":"### Existing repo, or changes <sup>[[1]](http://jasonkarns.com/blog/subdirectory-checkouts-with-git-sparse-checkout/)</sup>\n\n git config core.sparsecheckout true\n echo some/dir/ >> .git/info/sparse-checkout\n echo another/sub/tree >> .git/info/sparse-checkout\n git read-tree -mu HEAD\n"},{"_id":"3c6e3db873ff47ac7100001d","treeId":"37ff2da057a8f60d03000018","seq":1,"position":3,"parentId":"3c6e167873ff47ac71000019","content":"### Disable <sup>[[1]](http://schacon.github.io/git/git-read-tree.html#_sparse_checkout)</sup>\n(unverified)\n\n echo '*' > .git/info/sparse-checkout\n git read-tree -mu HEAD\n git config core.sparsecheckout false\n"},{"_id":"5366a1b7276bb07a6a000024","treeId":"37ff2da057a8f60d03000018","seq":2121560,"position":4.90625,"parentId":null,"content":"## Retrieve a file from specific revision\n\nSources: [stackoverflow](http://stackoverflow.com/questions/610208/how-to-retrieve-a-single-file-from-specific-revision-in-git)"},{"_id":"5366a426276bb07a6a000025","treeId":"37ff2da057a8f60d03000018","seq":2121572,"position":1,"parentId":"5366a1b7276bb07a6a000024","content":" git show $REV:$PATH\n\nSince git ~1.7+, `$PATH` can be relative with `./path`."},{"_id":"6feb83a8c88a4edacd000052","treeId":"37ff2da057a8f60d03000018","seq":8595567,"position":2,"parentId":"5366a1b7276bb07a6a000024","content":"Alternatively, if the file is to be restored at its original place, a shortcut is:\n\n git checkout $REV $PATH\n\n*Source: http://stackoverflow.com/a/2734035*"},{"_id":"60164f449bbfa86d0d00002e","treeId":"37ff2da057a8f60d03000018","seq":5535841,"position":4.9140625,"parentId":null,"content":"## Browse deleted files per commit\n\nSource: [stackoverflow](http://stackoverflow.com/a/953573/98528)"},{"_id":"601650f29bbfa86d0d00002f","treeId":"37ff2da057a8f60d03000018","seq":5535842,"position":1,"parentId":"60164f449bbfa86d0d00002e","content":" git log --diff-filter=D --summary"},{"_id":"6a1a5b73e079b665ba000049","treeId":"37ff2da057a8f60d03000018","seq":7719985,"position":4.916015625,"parentId":null,"content":"## List all files in repo\n"},{"_id":"6a1a5bcae079b665ba00004a","treeId":"37ff2da057a8f60d03000018","seq":7719992,"position":1,"parentId":"6a1a5b73e079b665ba000049","content":"* `git ls-tree --full-tree -r HEAD` &mdash; list all tracked files already in repo *([via](http://stackoverflow.com/a/8533413/98528))*;\n* `git ls-files` &mdash; list files including staged *([via](http://stackoverflow.com/a/14406253/98528))*;"},{"_id":"65948a08416d884d9f000036","treeId":"37ff2da057a8f60d03000018","seq":6577409,"position":4.91796875,"parentId":null,"content":"## commit: show full diff in editor\n\n*Source: [stackoverflow](http://stackoverflow.com/questions/4750148/git-show-index-diff-in-commit-message-as-comment)*"},{"_id":"65948bce416d884d9f000037","treeId":"37ff2da057a8f60d03000018","seq":6577410,"position":1,"parentId":"65948a08416d884d9f000036","content":" git commit --verbose"},{"_id":"6649f3e8c276bfeb4e000039","treeId":"37ff2da057a8f60d03000018","seq":6698693,"position":4.919921875,"parentId":null,"content":"## log/diff: file names only\n\n*Source: [stackoverflow](http://stackoverflow.com/a/14224142)*"},{"_id":"6649f542c276bfeb4e00003a","treeId":"37ff2da057a8f60d03000018","seq":6698698,"position":1,"parentId":"6649f3e8c276bfeb4e000039","content":" git log --pretty=\"format:\" --name-only [RANGE...]"},{"_id":"56a5ae937ba505b0eb000037","treeId":"37ff2da057a8f60d03000018","seq":2643923,"position":4.921875,"parentId":null,"content":"## Git attic: list deleted files"},{"_id":"56a5af597ba505b0eb000038","treeId":"37ff2da057a8f60d03000018","seq":2643926,"position":1,"parentId":"56a5ae937ba505b0eb000037","content":"````\n#!/bin/sh\n# git-attic [-M] [PATH] - list deleted files of Git repositories\n#\n# Use -M to not show renamed files, and other git-log options as you like.\n\ngit log --raw --no-renames --date=short --format=\"%h %cd\" \"$@\" |\n awk '/^[0-9a-f]/ { commit=$1; date=$2 }\n /^:/ && $5 == \"D\" { print date, commit \"^:\" $6 }' |\n git -p column\n````\n\n*Source: http://chneukirchen.org/blog/archive/2013/01/a-grab-bag-of-git-tricks.html*"},{"_id":"593a60e1fa7f33d274000029","treeId":"37ff2da057a8f60d03000018","seq":3053144,"position":4.9296875,"parentId":null,"content":"## Git submodule from existing .git subdir\n"},{"_id":"593a61dafa7f33d27400002a","treeId":"37ff2da057a8f60d03000018","seq":7720037,"position":1,"parentId":"593a60e1fa7f33d274000029","content":"````\nORIGIN_URL=$( git --git-dir $SUBREPO/.git config --get remote.origin.url | tee /dev/stderr )\n\ngit submodule add $ORIGIN_URL $SUBREPO\n````\n\n*Sources: [man git-submodule](https://www.kernel.org/pub/software/scm/git/docs/git-submodule.html), [remote.origin.url](http://stackoverflow.com/a/4090938)*"},{"_id":"66dc40579a5318cae200003d","treeId":"37ff2da057a8f60d03000018","seq":6808927,"position":4.93359375,"parentId":null,"content":"## Ways to specify a commit\n"},{"_id":"66dc40f09a5318cae200003e","treeId":"37ff2da057a8f60d03000018","seq":6809083,"position":1,"parentId":"66dc40579a5318cae200003d","content":"Commit:\n\n- `HEAD^` -- commit before HEAD\n - `HEAD^2` -- chooses other parent in merge commits\n - `HEAD^^`, `HEAD^^^`, ... -- grandparent of HEAD, grand-grandparent, etc.\n- `HEAD~3` = `HEAD^^^` = `HEAD^1^1^1`\n- `:/\"commit message regexp\"` -- newest commit with regexp match in commit message, reachable from anywhere\n - `v0.1^{/\"commit message regexp\"}` -- newest commit with regexp, reachable from *v0.1*\n- `refs/heads/master`, `refs/tags/v0.1` -- \"fully qualified\" names of: branch *master*, tag *v0.1*\n\n*(See: git help revisions)*"},{"_id":"66dc5a319a5318cae200003f","treeId":"37ff2da057a8f60d03000018","seq":6809081,"position":2,"parentId":"66dc40579a5318cae200003d","content":"Range of commits:\n\n- `HEAD^!` ≟ `HEAD^..HEAD`"},{"_id":"536532aed958b5bc3b000024","treeId":"37ff2da057a8f60d03000018","seq":2119665,"position":4.9375,"parentId":null,"content":"# Gerrit"},{"_id":"536532eed958b5bc3b000025","treeId":"37ff2da057a8f60d03000018","seq":2119666,"position":4.96875,"parentId":null,"content":"Fetch all reviews of a particular change\n"},{"_id":"5365345dd958b5bc3b000026","treeId":"37ff2da057a8f60d03000018","seq":2119682,"position":1,"parentId":"536532eed958b5bc3b000025","content":"Note: for change NNN, ***NN := NNN mod 100*** (e.g. for NNN=187, NN=87).\n\n git fetch gerrit refs/changes/NN/NNN/*:refs/changes/NN/NNN/*\n\n*Based on: https://blogs.gnome.org/markmc/2011/09/25/gerrit-patch-review-from-the-command-line/*"},{"_id":"385c9350b13fad348e000011","treeId":"37ff2da057a8f60d03000018","seq":1,"position":5,"parentId":null,"content":"# NON-git"},{"_id":"385c93f5b13fad348e000012","treeId":"37ff2da057a8f60d03000018","seq":1,"position":6,"parentId":null,"content":"## find most recent files, recursively\n"},{"_id":"385c9510b13fad348e000013","treeId":"37ff2da057a8f60d03000018","seq":1,"position":1,"parentId":"385c93f5b13fad348e000012","content":" find DIRNAME -type f -print0 |\n xargs -0 stat --format '%Y :%y %n' 2>/dev/null |\n sort -nr |\n cut -d: -f2- |\n head\n\nbased on: http://stackoverflow.com/questions/5566310/how-to-recursively-find-and-list-the-latest-modified-files-in-a-directory-with-s"},{"_id":"6923143cf981145c19000044","treeId":"37ff2da057a8f60d03000018","seq":7556750,"position":6.5,"parentId":null,"content":"## vim: various stuff\n"},{"_id":"5b60f3688f307226c700002b","treeId":"37ff2da057a8f60d03000018","seq":7556751,"position":1,"parentId":"6923143cf981145c19000044","content":"## vim: reopen all files edited before crash/kill"},{"_id":"5b60f5628f307226c700002c","treeId":"37ff2da057a8f60d03000018","seq":4784549,"position":1,"parentId":"5b60f3688f307226c700002b","content":"[FIXME]\n\n vim -r $(find . -regex '.*/\\.\\(.*\\.\\)?sw[po]')\n # or, vim -p + 'cut'? kinda:\n vim -p $(find . -regex '.*/\\.\\(.*\\.\\)?sw[po]' | sed 's/\\.[^.]*$//' )\n # maybe better:\n vim -p $(ls -1t $(find . -regex '.*/\\.\\(.*\\.\\)?sw[po]' ) | sed 's#/\\.\\([^/]*\\)\\.[^.]*$#/\\1#')\n\n*Based on: [:help recovery](http://vimdoc.sourceforge.net/htmldoc/usr_11.html#11.2)*"},{"_id":"62e5b1771f12a78c75000036","treeId":"37ff2da057a8f60d03000018","seq":7556752,"position":2,"parentId":"6923143cf981145c19000044","content":"## vim: new buffer (pseudo-\"scratch\")\n\n :new\n\n*Source: [vim wikia](http://vim.wikia.com/wiki/Vim_buffer_FAQ)*"},{"_id":"76b93a1934738c613e000052","treeId":"37ff2da057a8f60d03000018","seq":9611113,"position":2.5,"parentId":"6923143cf981145c19000044","content":"## vim: insert/paste current directory name\n\nUseful for naming Go packages. Uses the \"expression register\" `\"=`. \n\nIn ***normal mode***:\n\n \"=expand(\"%:h:t\")<Enter>p\n\nIn ***insert mode*** (equivalent but using `<C-R>`):\n\n <C-R>=expand(\"%:h:t\")<Enter>\n\nFor more info about `%:h:t` etc., see [`:help filename-modifiers`](http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers).\n\n*Source: [[1]](http://unix.stackexchange.com/questions/8101/how-to-insert-the-result-of-a-command-into-the-text-in-vim) [[2]](http://vim.wikia.com/wiki/Insert_current_filename) [[3]](http://stackoverflow.com/a/16486089/98528)*"},{"_id":"69231624f981145c19000045","treeId":"37ff2da057a8f60d03000018","seq":7556759,"position":3,"parentId":"6923143cf981145c19000044","content":"## Various often used stuff\n"},{"_id":"6923171bf981145c19000046","treeId":"37ff2da057a8f60d03000018","seq":7556828,"position":4,"parentId":"6923143cf981145c19000044","content":"### Windows, tabs, buffers\n\n- [Ctrl-w], [Shift-T] — \"promote\" current window into a new tab\n- `:tabmv -1` — move current tab 1 position to the left (similar for +1 etc.)\n- `:tabcl` — close current tab\n- `:tabo` — leave only current tab (close all others)\n- `:tabdo windo e` — reload all buffers in all windows in all tabs"},{"_id":"69558ef9f981145c19000047","treeId":"37ff2da057a8f60d03000018","seq":7604044,"position":5,"parentId":"6923143cf981145c19000044","content":"### Quickfix window\n\n* `:cex system('go build ./...')` — run specified command and load the result in quickfix list. If the result can be parsed using 'errorformat', cursor will be moved to position of first error.\n * ...` | copen` — add after above command to also show the quickfix window\n* `:cn` / `:cp` — jump to next/previous error from quickfix list\n* `:ccl` — close quickfix window\n\n[TODO] describe stuff in 'set errorformat'"},{"_id":"696f0c13f981145c19000048","treeId":"37ff2da057a8f60d03000018","seq":10342650,"position":6,"parentId":"6923143cf981145c19000044","content":"### Registers (copy, paste, ...)\n\n- `:let @a = \"foobar\"` — put text `foobar` in register `a`\n- `:let @f = @%` — put current filename in register `f`; can be then reopened in a different window with `:e <C-R>f`"},{"_id":"62965aa2a8be1063a2000033","treeId":"37ff2da057a8f60d03000018","seq":5986001,"position":8,"parentId":null,"content":"## ack: exclude some files from search\n\n*Source: [stackoverflow.com](http://stackoverflow.com/a/19458758/98528)*"},{"_id":"62965c74a8be1063a2000034","treeId":"37ff2da057a8f60d03000018","seq":5986014,"position":1,"parentId":"62965aa2a8be1063a2000033","content":"To exclude _*_test.go_ (and also pipe through less while keeping colours and grouping):\n\n ack --go $PATTERN \\\n --pager='less -R' --ignore-file=match:_test.go"},{"_id":"65d40b82281aa0f21e000038","treeId":"37ff2da057a8f60d03000018","seq":6622459,"position":2,"parentId":"62965aa2a8be1063a2000033","content":"Other examples of excludes:\n\n --ignore-dir=_vendor\n --ignore-file=match:'\\.(txt|out|log)$'"},{"_id":"668f617067ea131b6b00003c","treeId":"37ff2da057a8f60d03000018","seq":11451936,"position":9,"parentId":null,"content":"## ssh: break hanged session, and other tricks\n\n*Source: [stackoverflow](http://askubuntu.com/a/29952)*"},{"_id":"668f62ec67ea131b6b00003d","treeId":"37ff2da057a8f60d03000018","seq":10338636,"position":1,"parentId":"668f617067ea131b6b00003c","content":"> [Enter] [`~`] [`.`]\n\nAlso, to break out of a *nested* hanged session (i.e. ssh within ssh), repeat [`~`] *n* times. E.g. for session 1 level deep:\n\n> [Enter] [`~`] [`~`] [`.`]"},{"_id":"7ca80c9ba7c7eb879d00005b","treeId":"37ff2da057a8f60d03000018","seq":11451944,"position":2,"parentId":"668f617067ea131b6b00003c","content":"**Other tricks:**\n\n> [Enter][`~`][`#`] — list forwarded ports in current session\n>\n> [Enter][`~`][`?`] — list all available `~`-commands\n\n*Source: [lonesysadmin.net](https://lonesysadmin.net/2011/11/08/ssh-escape-sequences-aka-kill-dead-ssh-sessions/amp/) ([via](https://news.ycombinator.com/item?id=15538744))*"},{"_id":"77e87695906c73d48b000055","treeId":"37ff2da057a8f60d03000018","seq":11451945,"position":9.5,"parentId":null,"content":"## ssh: screenshot of remote machine's display"},{"_id":"77e877a6906c73d48b000056","treeId":"37ff2da057a8f60d03000018","seq":9814962,"position":1,"parentId":"77e87695906c73d48b000055","content":"```\n $ ssh -t -i $PRIVATE_KEY $USER@$MACHINE 'sudo -u $GUI_USER bash -c \"DISPLAY=:0.0 import -window root -screen /home/$GUI_USER/foo.png\" '\n[sudo] password for $USER:\nConnection to $MACHINE closed.\n```"},{"_id":"7ca801bba7c7eb879d00005c","treeId":"37ff2da057a8f60d03000018","seq":11451947,"position":9.75,"parentId":null,"content":"## ssh: reverse tunnel\n"},{"_id":"7ca7febaa7c7eb879d00005d","treeId":"37ff2da057a8f60d03000018","seq":11452594,"position":1,"parentId":"7ca801bba7c7eb879d00005c","content":"1. on *$LOCAL* machine, pick *$USER* via whom the tunnel will be built\n2. if $USER has SSH login disabled, [enable it temporarily](https://askubuntu.com/questions/282806/how-to-enable-or-disable-a-user):\n\n LOCAL$ sudo usermod --expiredate \"\" $USER\n LOCAL$ sudo passwd -u $USER\n\n3. deploy private SSH key on *$REMOTE* machine (e.g. as *$KEY_PATH*), and put the public counterpart of the key in */home/$USER/.ssh/authorized_keys* on $LOCAL machine\n > Note: the private key must have `chmod 400`\n4. setup a reverse tunnel, *on $REMOTE machine*:\n\n REMOTE$ ssh -i $KEY_PATH -o StrictHostKeyChecking=no \\\n -Nf -R 16003:localhost:22 $USER@$LOCAL\n\n5. login via the reverse tunnel:\n\n LOCAL$ ssh localhost -p 16003\n\n6. ***do what you need via reverse ssh...***\n7. cleanup:\n\n REMOTE$ rm $KEY_PATH\n REMOTE$ ps aux | grep ssh\n REMOTE$ kill ... # kill the process from step 4\n\n If step 2 was done, reverse it:\n\n LOCAL$ sudo usermod --expiredate 1 $USER\n LOCAL$ sudo passwd -l $USER"},{"_id":"7b78ac04c3ad6d85e100005f","treeId":"37ff2da057a8f60d03000018","seq":11640857,"position":9.875,"parentId":null,"content":"## ssh: debug connection problems\n"},{"_id":"7b78ab6cc3ad6d85e1000060","treeId":"37ff2da057a8f60d03000018","seq":11640862,"position":1,"parentId":"7b78ac04c3ad6d85e100005f","content":"### **On server**\n\nIf possible (root access), run an extra instance of *sshd* on a distinct port, with detailed logs printed to console:\n\n $ sudo /usr/sbin/sshd -d -p 2222\n\n*Source: [unix.stackexchange](https://unix.stackexchange.com/a/55481/11352)*\n\n### **On client**\n\nRun ssh with `-vvv` flag for detailed logs. Together with the extra server as above, this may look like:\n\n $ ssh -vvv -p 2222 $USER@$HOST\n\n*Source: [askubuntu](https://askubuntu.com/a/69867/111779)*\n"},{"_id":"77f7761ce13e604121000074","treeId":"37ff2da057a8f60d03000018","seq":12406664,"position":9.9375,"parentId":null,"content":"## ssh: view fingerprint of server host key"},{"_id":"77f774cee13e604121000075","treeId":"37ff2da057a8f60d03000018","seq":13086794,"position":1,"parentId":"77f7761ce13e604121000074","content":"Best solution:\n\n $ ssh-keygen -E md5 -lf <( ssh-keyscan localhost 2>/dev/null )\n $ ssh-keygen -E sha256 -lf <( ssh-keyscan localhost 2>/dev/null )\n\n*Sources: unix.stackexchange [[1]](https://unix.stackexchange.com/a/408349/11352) [[2]](https://unix.stackexchange.com/a/268692/11352)*\n\n---\n\nAlternative:\n\n $ ssh-keygen -E md5 -lf /etc/ssh/ssh_host_rsa_key.pub\n $ ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ecdsa_key.pub\n\nOne-liner:\n\n ls -1 /etc/ssh/ssh_host_*.pub | join -j2 <( printf \"md5\\nsha256\" ) - | awk '{system(\"ssh-keygen -E \"$1\" -lf \"$2)}'\n\nsame but wrapped:\n\n ls -1 /etc/ssh/ssh_host_*.pub |\n join -j2 <( printf \"md5\\nsha256\" ) - |\n awk '{system(\"ssh-keygen -E \"$1\" -lf \"$2)}'\n\n*Sources:*\n - *cartesian product in bash: [comment on catonmat.net](http://www.catonmat.net/c/1391)*\n\n"},{"_id":"706846be1b28417d3a000073","treeId":"37ff2da057a8f60d03000018","seq":13924029,"position":9.96875,"parentId":null,"content":"## ssh: view remembered/stored fingerprints of hosts\n"},{"_id":"7068461d1b28417d3a000074","treeId":"37ff2da057a8f60d03000018","seq":13924030,"position":1,"parentId":"706846be1b28417d3a000073","content":"For all hosts:\n\n $ ssh-keygen -l -f ~/.ssh/known_hosts\n $ ssh-keygen -l -f ~/.ssh/known_hosts -E md5\n\nFor single host:\n\n $ ssh-keygen -l -f ~/.ssh/known_hosts -F $HOST:$PORT\n $ ssh-keygen -l -f ~/.ssh/known_hosts -F $HOST:$PORT -E md5\n\n*Source: [stackoverflow](https://superuser.com/a/529145/12184)* "},{"_id":"678a2d57cced290396000040","treeId":"37ff2da057a8f60d03000018","seq":7900684,"position":10,"parentId":null,"content":"## Go: tips, tricks & patterns\n\n\n"},{"_id":"678a2f9acced290396000041","treeId":"37ff2da057a8f60d03000018","seq":7900682,"position":1,"parentId":"678a2d57cced290396000040","content":"### Windows: ignore vendor in go test\n\nPowershell script [TODO: how one runs it?]:\n\n $GOPKG = (go list ./... ) | Out-String -stream | select-string -NotMatch vendor\n iex \"go test -v $GOPKG\"\n\n*Source: [golang.org/issue/15355](https://github.com/golang/go/issues/15355)*\n\n"},{"_id":"6b4ad0c572e50a63fd00004b","treeId":"37ff2da057a8f60d03000018","seq":7900688,"position":2,"parentId":"678a2d57cced290396000040","content":"### Pattern 1: poor man's pattern-matching switch\n\n```go\nfunc ... {\n type change struct {from, to X}\n switch (change{a, b}) {\n case change{Foo, Bar}:\n ...\n }\n```\n\n"},{"_id":"6b4ad84f72e50a63fd00004c","treeId":"37ff2da057a8f60d03000018","seq":7900694,"position":3,"parentId":"678a2d57cced290396000040","content":"### Pattern 2: easy reentrant Close for goroutines\n\n```go\nfunc NewX() *X {\n x := &X{\n quit: make(chan struct{}),\n }\n go x.loop()\n return x\n}\n\nfunc (x *X) Close() error {\n <-x.quit\n}\n\nfunc (x *X) loop() {\n for {\n select {\n case x.quit<-struct{}{}:\n close(x.quit)\n return\n case y, ok := <-x.myChan:\n if !ok {\n // myChan closed, but we still have to allow x.Close()\n close(x.quit)\n return\n }\n // ... real work ...\n }\n}\n```\n"},{"_id":"69150eb4f981145c19000042","treeId":"37ff2da057a8f60d03000018","seq":7546686,"position":11,"parentId":null,"content":"## bash: keyboard shortcuts\n"},{"_id":"69150f53f981145c19000043","treeId":"37ff2da057a8f60d03000018","seq":7546835,"position":1,"parentId":"69150eb4f981145c19000042","content":"### Commands reuse\n* **[Esc], [\\#]** (or **[Alt-#]** or [Alt-3] or [Esc], [3]) — insert comment sign (\"#\") at start of current line, then cancel the line (like Ctrl-C), saving it to history (for later fixing/completing & reuse)\n* **[Alt-.]** — paste last argument from previous command (press again for earlier commands)\n * **[Alt-*n*], [Alt-.]** — paste *n*-th argument from previous command (starting from 0)\n* **[Ctrl-r], *some-text*** — incremental search backwards through history\n\n### Moving, editing\n* **[Ctrl-a]** / **[Ctrl-e]** — move to start/end of current line\n* **[Alt-b]** / **[Alt-f]** — move 1 word backwards/forwards\n* **[Ctrl-k]** — kill (delete) part of line after cursor (to line end)\n* **[Shift-PgUp]** / **[Shift-PgDn]** — scroll terminal window up/down\n"},{"_id":"4af23d7f02ff3c910b000089","treeId":"37ff2da057a8f60d03000018","seq":20900889,"position":11.5,"parentId":null,"content":"## bash: tee 1st line to stderr as header\n"},{"_id":"4af23b8602ff3c910b00008a","treeId":"37ff2da057a8f60d03000018","seq":20900891,"position":1,"parentId":"4af23d7f02ff3c910b000089","content":" sed 1w/dev/stderr\n\n*Source: [GNU sed manual](https://www.gnu.org/software/sed/manual/sed.html#index-w-_0028write-file_0029-command)*"},{"_id":"7049c66804cfa1fbef00004f","treeId":"37ff2da057a8f60d03000018","seq":8650132,"position":12,"parentId":null,"content":"## netstat: what's listening on port\n"},{"_id":"7049c81104cfa1fbef000050","treeId":"37ff2da057a8f60d03000018","seq":8650140,"position":1,"parentId":"7049c66804cfa1fbef00004f","content":" sudo netstat -l -p | grep $PORT\n\n* `-l` &mdash; show listening server sockets\n* `-p` &mdash; show PID/program name\n* (`-W` &mdash; wide: don't truncate IP addresses)"},{"_id":"773173d80f6a90c0e8000052","treeId":"37ff2da057a8f60d03000018","seq":9703304,"position":13,"parentId":null,"content":"## apt-get: Ubuntu packages installer\n"},{"_id":"773174810f6a90c0e8000053","treeId":"37ff2da057a8f60d03000018","seq":9703320,"position":1,"parentId":"773173d80f6a90c0e8000052","content":"## List files in package\n\nFor installed package:\n\n dpkg-query -L $PACKAGE\n\nOther possibilities: http://askubuntu.com/a/32509/111779"},{"_id":"781d2e67bc95e7a81c000056","treeId":"37ff2da057a8f60d03000018","seq":9843026,"position":15,"parentId":null,"content":"## virtualbox: fix after upgrading Linux kernel version\n"},{"_id":"781d2f77bc95e7a81c000057","treeId":"37ff2da057a8f60d03000018","seq":9843027,"position":1,"parentId":"781d2e67bc95e7a81c000056","content":" $ sudo dpkg-reconfigure virtualbox-dkms\n $ sudo dpkg-reconfigure virtualbox\n $ sudo modprobe vboxdrv\n\n([via](https://ubuntuforums.org/showthread.php?t=2055886))"},{"_id":"78a1be51a284219a92000058","treeId":"37ff2da057a8f60d03000018","seq":9920607,"position":16,"parentId":null,"content":"## psql: human-readable *bytea* fields in Postgres\n\n`set bytea_output='escape';` ([via](http://dba.stackexchange.com/q/69238))"},{"_id":"7c23979d9e309ec712000059","treeId":"37ff2da057a8f60d03000018","seq":10437934,"position":17,"parentId":null,"content":"## socat: forward serial (COM) port over SSH/TCP"},{"_id":"7c2398679e309ec71200005a","treeId":"37ff2da057a8f60d03000018","seq":10437949,"position":1,"parentId":"7c23979d9e309ec712000059","content":"Login to remote server with serial port, then start serving the port:\n\n client$ ssh -L 3334:localhost:3334 server\n server$ sudo socat -ddd -ddd /dev/ttyS0,raw,b115200,$(cat stty-flags | sed '1,4d' | sed 's/-\\([^ ]*\\)/\\1=0/g' | tr ' ' '\\n' | grep -vE 'cmspar|iutf8|extproc' | paste -d, -s ) tcp-l:3334\n\nCreate a local virtual serial port (will get assigned a name in `/dev/pts/*`) forwarded to remote one:\n\n client$ sudo socat -ddd -ddd pty,link=foobar,raw,echo=0 tcp:localhost:3334\n"},{"_id":"7b1bc0a076b3a8e5c2000060","treeId":"37ff2da057a8f60d03000018","seq":11690711,"position":18,"parentId":null,"content":"## curl: download from domain on virtual host by IP"},{"_id":"7b1bbf7a76b3a8e5c2000061","treeId":"37ff2da057a8f60d03000018","seq":11690721,"position":1,"parentId":"7b1bc0a076b3a8e5c2000060","content":" $ curl --resolve \"named-host.com:80:$IP\" http://named-host.com\n\n*Source: some stackoverflow*"},{"_id":"7a8bf8a8972a0b263e000081","treeId":"37ff2da057a8f60d03000018","seq":11771102,"position":19,"parentId":null,"content":"## openssl: view decoded details of a certificate"},{"_id":"7a8bf78f972a0b263e000082","treeId":"37ff2da057a8f60d03000018","seq":11771104,"position":1,"parentId":"7a8bf8a8972a0b263e000081","content":"\n $ openssl x509 -in $CERTFILE.cer -noout -text\n\n*Source: [serverfault.com](https://serverfault.com/a/215617/74509)*"},{"_id":"756635d9c19eeb81a5000077","treeId":"37ff2da057a8f60d03000018","seq":12818093,"position":19.5,"parentId":null,"content":"## openssl: view expiration date of website's certificate"},{"_id":"7566353bc19eeb81a5000078","treeId":"37ff2da057a8f60d03000018","seq":12818099,"position":1,"parentId":"756635d9c19eeb81a5000077","content":" $ echo | openssl s_client -connect $HOST:443 2>/dev/null |\n openssl x509 -noout -enddate\n notAfter=...\n\n*Source: [realguess.net](https://realguess.net/2016/10/11/a-cli-method-to-check-ssl-certificate-expiration-date/)*"},{"_id":"740ffe9813178b25a6000070","treeId":"37ff2da057a8f60d03000018","seq":13085963,"position":19.75,"parentId":null,"content":"## openssl: fingerprints"},{"_id":"740ffc7f13178b25a6000071","treeId":"37ff2da057a8f60d03000018","seq":13085966,"position":1,"parentId":"740ffe9813178b25a6000070","content":"Fingerprints for **~/.ssh/authorized_keys{,2}**:\n\n cat ~/.ssh/authorized_keys | xargs -n1 -I% bash -c 'ssh-keygen -l -f /dev/stdin <<<\"%\"'\n\nsame but wrapped:\n\n cat ~/.ssh/authorized_keys |\n xargs -n1 -I% bash -c 'ssh-keygen -l -f /dev/stdin <<<\"%\"'"},{"_id":"740ff91913178b25a6000072","treeId":"37ff2da057a8f60d03000018","seq":13085968,"position":2,"parentId":"740ffe9813178b25a6000070","content":"Host fingerprints: **see SSH command above**"},{"_id":"77faca13e13e604121000072","treeId":"37ff2da057a8f60d03000018","seq":12404747,"position":20,"parentId":null,"content":"## IP: check publicly visible IP"},{"_id":"77fac996e13e604121000073","treeId":"37ff2da057a8f60d03000018","seq":12404751,"position":1,"parentId":"77faca13e13e604121000072","content":"Any of the following should do:\n\n $ curl ipinfo.io/ip\n $ curl ifconfig.me\n $ curl icanhazip.com\n $ curl ident.me\n $ curl checkip.amazonaws.com\n\n*Source: [askubuntu.com](https://askubuntu.com/q/95910/111779)*"},{"_id":"77f76e52e13e604121000076","treeId":"37ff2da057a8f60d03000018","seq":12406715,"position":21,"parentId":null,"content":"## python: simple WWW server"},{"_id":"77f76e0fe13e604121000077","treeId":"37ff2da057a8f60d03000018","seq":12406723,"position":1,"parentId":"77f76e52e13e604121000076","content":" $ cat ... > index.html\n $ python -m SimpleHTTPServer $PORT\n\n*Source: [gist](https://gist.github.com/willurd/5720255)*"}],"tree":{"_id":"37ff2da057a8f60d03000018","name":"git","publicUrl":"git-notes"}}