Split top commit in half

More at source: On undoing, fixing, or removing commits in git - A git choose-your-own-adventure!ⓡ

See also Post-Production Editing Using Git for great tutorial on git rebase -i $EARLIER_SHA

$ git reset HEAD^
$ git add -p

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.


Transplant a patch from unrelated repository

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

Single commit/patch

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

where format-patch options are:

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


See: git help apply

Does not create a commit.

Show history using pretty ASCII-Art tree graph

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

Remove local changes

More at source: How to revert all local changes in a GIT managed project to previous state?

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

Merge, ignoring whitespace

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

git merge -Xignore-space-change

Source: http://stackoverflow.com/questions/18319485/forcing-git-to-merge-add-add-conflicts#comment26892583_18319485

To create a merge like in diagram below:

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

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

git checkout old
git merge -ssubtree snapshot -Xignore-space-change

3-way diff of a file during merge/rebase

Sources: Git Conflict Resolution, man git

git -c merge.conflictstyle=diff3 checkout -m $FILE

Search repo/history

a) Find commits which add/remove lines matching a regex (i.e. search history)

git log -G"$REGEX" -p --decorate -a

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

Partial (“sparse”) checkouts

Git 1.7+

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]


echo '*' > .git/info/sparse-checkout
git read-tree -mu HEAD
git config core.sparsecheckout false

Retrieve a file from specific revision

Sources: stackoverflow

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

Browse deleted files per commit

Source: stackoverflow

git log --diff-filter=D --summary

List all files in repo

commit: show full diff in editor

Source: stackoverflow

git commit --verbose

log/diff: file names only

Source: stackoverflow

git log --pretty="format:" --name-only [RANGE...]

Git attic: list deleted files

# 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

Git submodule from existing .git subdir

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

Ways to specify a commit


(See: git help revisions)

Range of commits:


Fetch all reviews of a particular change

Note: for change NNN, NN := NNN mod 100 (e.g. for NNN=187, NN=87).

git fetch gerrit refs/changes/NN/NNN/*:refs/changes/NN/NNN/*

Based on: https://blogs.gnome.org/markmc/2011/09/25/gerrit-patch-review-from-the-command-line/


find most recent files, recursively

find DIRNAME -type f -print0 |
  xargs -0 stat --format '%Y :%y %n' 2>/dev/null |
  sort -nr |
  cut -d: -f2- |

based on: http://stackoverflow.com/questions/5566310/how-to-recursively-find-and-list-the-latest-modified-files-in-a-directory-with-s

vim: various stuff

vim: reopen all files edited before crash/kill


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

vim: new buffer (pseudo-“scratch”)


Source: vim wikia

vim: insert/paste current directory name

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

In normal mode:


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


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

Source: [1] [2] [3]

Various often used stuff

Windows, tabs, buffers

Quickfix window

[TODO] describe stuff in ‘set errorformat’

Registers (copy, paste, …)

Source: stackoverflow.com

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:


ssh: break hanged session, and other tricks

Source: stackoverflow

[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: screenshot of remote machine’s display

 $ 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.

ssh: reverse tunnel

  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$ 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

ssh: debug connection problems

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

ssh: view fingerprint of server host key

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]


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


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)}'


ssh: view remembered/stored fingerprints of hosts

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

Go: tips, tricks & patterns

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 {

func (x *X) loop() {
  for {
    select {
    case x.quit<-struct{}{}:
    case y, ok := <-x.myChan:
      if !ok {
        // myChan closed, but we still have to allow x.Close()
      // ... real work ...

bash: keyboard shortcuts

Commands reuse

Moving, editing

bash: tee 1st line to stderr as header

sed 1w/dev/stderr

Source: GNU sed manual

netstat: what’s listening on port

sudo netstat -l -p | grep $PORT

apt-get: Ubuntu packages installer

List files in package

For installed package:

dpkg-query -L $PACKAGE

Other possibilities: http://askubuntu.com/a/32509/111779

virtualbox: fix after upgrading Linux kernel version

$ sudo dpkg-reconfigure virtualbox-dkms
$ sudo dpkg-reconfigure virtualbox
$ sudo modprobe vboxdrv


psql: human-readable bytea fields in Postgres

set bytea_output='escape'; (via)

socat: forward serial (COM) port over SSH/TCP

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: download from domain on virtual host by IP

$ curl --resolve "named-host.com:80:$IP" http://named-host.com

Source: some stackoverflow

openssl: view decoded details of a certificate

$ openssl x509 -in $CERTFILE.cer -noout -text

Source: serverfault.com

openssl: view expiration date of website’s certificate

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

Source: realguess.net

openssl: fingerprints

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

IP: check publicly visible IP

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

python: simple WWW server

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

Source: gist