Following on from a previous post about rewriting indentation for an entire git repo, another reason to rewrite the history of a whole repo is to change the email address or name mentioned in commits.

Once again, be aware that rewriting history will cause problems if other people have clones of the repo so make sure you understand the risks before doing this!

To change the author name and email address for every commit, you can run this:

1
2
3
4
5
6
git filter-branch -f --env-filter "
  GIT_AUTHOR_NAME='YOUR_NAME'
  GIT_AUTHOR_EMAIL='YOUR_EMAIL'
  GIT_COMMITTER_NAME='YOUR_NAME'
  GIT_COMMITTER_EMAIL='YOUR_EMAIL'
" HEAD

This will blindly replace all the commits with the details given, but if other people have contributed, you may need to be a bit more careful and only replace your own:

1
2
3
4
5
6
7
8
9
10
11
12
git filter-branch --commit-filter "
  if [ "$GIT_COMMITTER_NAME" = 'YOUR_ORIGINAL_NAME'];
  then
    GIT_AUTHOR_NAME='YOUR_NEW_NAME'
    GIT_AUTHOR_EMAIL='YOUR_NEW_EMAIL'
    GIT_COMMITTER_NAME='YOUR_NEW_NAME'
    GIT_COMMITTER_EMAIL='YOUR_NEW_EMAIL'
    git commit-tree "$@";
  else
    git commit-tree "$@";
  fi
" HEAD

If you understand the risks of rewriting history for a shared repository, you can force push with the -f flag:

1
git push -f

Then, to ensure future commits don’t use the wrong name and email, you can set it explicity for this particular repo (instead of globally) with these commands:

1
2
git config user.email "your_email@example.com"
git config user.email "your_email@example.com"

Keep in mind this will only work for this particular clone as the details will be stored locally in .git/config.

By default, the sudo command does not pass your current shell environment to the new process.

I’ve added the function below to my bash configuration which will gives me an esudo command. This command works much like sudo but it will pass my current environment to the new process.

1
function esudo { sudo -E bash -c "$*"; }

If you use a ruby version manager, you’ll know that they generally rely on environment variables, so rvm provide the rvmsudo command for this purpose. I’ve since switched to chruby and I couldn’t seem to find an equivalent, but this has solved the issue for me.

I have a fairly terrible memory but I’ve found writing and referring back to cheatsheets to be a pretty effective way to memorize things.

I ended up referring back to my previous cheatsheet on git reset quite a few times soon after I wrote it, so when I came across this great post on regex features in ruby I thought I’d share the lookarounds section because I always forget those too!

Syntax Description Example Result
(?=X) Positive lookahead "Ruby"[/.(?=b)/] "u"
(?!X) Negative lookahead "Ruby"[/.(?!u)/] "u"
(?<=X) Positive lookbehind "Ruby"[/(?<=u)./] "b"
(?<!X) Negative lookbehind "Ruby"[/(?<!R|^)./] "b"

Checkout the original blog post for the rest of the regex tips or the Idiosyncratic Ruby site for more ruby tips!

It seems the JavaScript community is divided into two camps when it comes to indentation conventions: two spaces or four?

I personally prefer two spaces mainly because its what I’m used to in Ruby, I find it easier on the eyes and just that little bit easier to keep my lines under 80 characters long (yes, I still think this is good practice).

Our team had come to a general consensus for using two spaces, but when we were starting a new project based on an existing project that used four spaces, we thought it would be nice to fix all the whitespace in one go.

In a rush, we made a commit that literally replaced all the whitespace with the following command:

1
find . -type f -exec sed -i "" "s/    /  /g" {} \;

The problem with this approach is that it makes going through commit messages harder. It means that when you use git annotate, every line with indentation is going to have the whitespace fix as the last commit, so then you would have to jump back another commit to get the actual commit message for that line, which can be fairly annoying.

Luckily, if you are forking an existing repository for a new project you have the luxury of being able to rewrite history without causing any pain to others as no one else would have checked it out yet.

Git provides a powerful command called filter-branch. It is designed to rewrite large amounts of history in one go. This can be useful to purge sensitive information from every commit or update an email address in the commit data, etc. The only problem with this is, just like rebasing, any existing checkouts will not be able to simply use git pull cleanly after the history has been rewritten upstream, but this isn’t a problem for new projects.

In order to execute the command above for every commit in our repo, we can make use of the --tree-filter option like this:

1
git filter-branch --tree-filter 'find . -type f -exec sed -i "" "s/    /  /g" {} \;' HEAD

Please note, this can take quite some time, especially for large repositories. You should also make sure there are no files that specifically need four spaces (like markdown files, etc.), otherwise you may want to restrict the find command to only effect files you know are safe to change (*.js for example).

For more information on rewriting history and git filter-branch, see this article and the documentation.

We all know that if you are going to be rendering user provided content on a HTML page, it should be sanitized just in case they include a nasty script tag or something.

React will automatically sanitize any string being rendered to the screen unless you jump through hoops first - which is great because making this difficult means its somewhat harder to inadvertently create a XSS vulnerability.

However, if you get a string from a human source and want to display that in a div tag while maintaining its newlines, this becomes a little harder because you don’t want to replace all \n characters with <br /> tags because this would mean you would also need to disable the sanitizing.

There are some libraries to deal with this sort of thing that implement white listing of tags, etc.
Another alternative would be using something like Markdown.
Even a simple <pre> tag will get you pretty far, but today I read an article that shows how you can achieve this with a little CSS:

1
2
3
.pre {
  white-space: pre-line;
}

For more details, I recommend having a read of this article.

If you ever needed to circumvent the browsers Same Origin Policy (SOP) so you don’t need to add Cross Origin Resource Sharing (CORS) headers just to test out an idea, here is a quick little hack to open a new instance of Chrome that will not enforce these security features:

1
alias unsafe-chrome='/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=~/Library/Application\ Support/Google/UnsafeChrome --disable-web-security 2> /dev/null'

The important options here are:

--disable-web-security - This will disable the Same Origin Policy
--user-data-dir=... - This launches a separate instance, with its own user data directory.
This prevents you from needing to close any current instances of chrome, otherwise running this command will just bring the existing instance into focus.

Another good thing about giving this instance its own user-data-dir is that you can give this instance its own settings. For example, this instance is not signed into my Google account and I’ve configured a bright red theme so I can easily tell the difference between my normal Chrome and my insecure Chrome!

I’ve been using Raspbmc for a while now, but I only just saw that it has been superseded by OSMC (and XBMC is now called Kodi, so with the long weekend I thought I’d upgrade.

The upgrade process is really simple. I backed up my existing installtion of Raspbmc, downloaded the offical OSMC installer from their site, installed it over the top and booted it up.

From here, there are only a few things to do. I entered my MPG2 and WVC1 codecs, setup my video sources and kicked off the scrapers and installed a few addons. The only other thing is setting up my TV remote. (I did this last time but forgot how, so this time I thought I’d blog it!)

Out of the box, my Samsung “Smart Touch” Remote (this one if you’re wondering) mostly just works, the only problem is the back button opens the context menu instead of going back!

To fix this, the first step is to find out what each button on the remote maps to in Kodi. Thanks to this great forum post by a user called “Knapster” this is really easy.

Just SSH to the pi, create a new file ~/.kodi/userdata/keymaps/remote.xml and paste this contents in it. Now reboot Kodi and everytime you press a button, you’ll get a notification on the screen of what command it is sending.

A quick way of doing that from an SSH session is like this:
(The default username and password are both osmc)

1
2
3
ssh osmc@<kodi-ip-address>
curl https://gist.githubusercontent.com/stevenocchipinti/42f2eca2a9f04ed9e52f/raw/remote.xml > ~/.kodi/userdata/keymaps/remote.xml
sudo reboot

In my case, everything seemed to make sense except the back button, which was actually sending title instead of back. As I don’t have a title button, I’m going to reassign that to be a back button instead.

First, lets replace our remote.xml with the default configuration, you can get these mappings from the installed Kodi files:

1
cp /usr/share/kodi/system/keymaps/remote.xml ~/.kodi/userdata/keymaps/remote.xml

This file has what every command does in every context and makes it easy to modify. Here is a diff of the changes I made for my remote:

1
2
3
4
5
6
7
8
9
10
11
12
58c58
<       <title>ContextMenu</title>
---
>       <title>Back</title>
74c74
<       <guide>ActivateWindow(TVGuide)</guide>
---
>       <guide>ActivateWindow(Home)</guide>
79c79
<       <red>ActivateWindow(TVChannels)</red>
---
>       <red>ContextMenu</red>

I’ve made the “title” button send the back command and because I don’t have a TV tuner connected, I’ve also re-assigned the “TV Guide” button to go to the home screen and the “Red” button to be the context menu button.
Interestingly, the channel up and down buttons on my remote we already assigned to page up and page down, which suits me great while I don’t have a TV Tuner.

After rebooting, I now have a functional remote control!

The reset command in git does quite a lot, but I always forget all its uses.
This is a cheatsheet based on this blog.

The reset command will:
1. Move whatever branch HEAD points to (stop here unless --soft)
2. THEN, make the Index look like that (stop here unless --hard)
3. THEN, make the Working Directory look like that

Commit level

Updates Current Branch? Updates Index? Updates Working Dir? Working Dir Safe?
reset --soft [commit] YES NO NO YES
reset (--mixed) [commit] YES YES NO YES
reset --hard [commit] YES YES YES NO
checkout [commit] NO YES YES YES

reset --soft [commit]
When given HEAD~, this undos the git commit
Will move the current branch back to the given commit, but not update the index or working directory
This provides similar functionality as git checkout --amend (but changing the whole commit, not just the message)

reset (--mixed) [commit] (default form)
When given HEAD~, this undos the git commit and the git add
Will move the current branch and update the index, but working directory will remain untouched

reset --hard [commit] (unsafe)
When given HEAD~, this undos the git commit, git add and also the changes in the working directory
Will update all three trees to match the given commit
This is useful to remove commits you don’t want
From a clean working tree, it is also useful to undo a conflicted (or not conflicted) git merge or a git pull
From a dirty working tree, use --merge instead, this will safely preserve your local changes
The --keep option is useful when removing some of the last commits while safely keeping your local changes

checkout [commit]
When given HEAD~, this will safely update the working directory and the index without moving the current branch
This will leave you in a detached HEAD state

File level

Updates Current Branch? Updates Index? Updates Working Dir? Working Dir safe?
reset (commit) [file] NO YES NO YES
checkout (commit) [file] NO NO YES NO

reset (commit) [file]
When given a file path, the first step of updating the branch that HEAD points to is skipped
Will update the index only to match commit, leaving both working directory and current branch untouched
From here, you could use git checkout to make the working directory match the index, although git checkout can do that with one command (see below)
The commit parameter will default to HEAD which effectively un-stages files

checkout (commit) [file] (unsafe)
Updates the working directory only, without changing the index, current branch or even what HEAD is pointing to
This would effectively be git reset --hard [branch] file, but this command does not exist

More info and examples in git reset --help

It’s so easy to write little scripts and execute them at a later time with the standard command-line tooling available in unix-like operating systems, but if you plan on having them execute while you are out and about, it would be nice to get a notification on your phone that it worked (or didn’t work).

If you’re happy with a simple email notification, then luckily this can be done with one simple line of code!

On a mac:

1
echo "Hello" | mail -s "Your alert" to-addr@example.com -f from-addr@example.com

On *nix:

1
echo "Hello" | mail -s "Your alert" to-addr@example.com -aFrom:from-addr@example.com

I’d love to learn Street Fighter 2, but there are just so many combos!
- The Vim Learning Curve is a Myth, Thoughtbot

A lot of people are scared of learning of vim because of the initial learning curve.

When learning vim for the first time there are lots of approaches, but two common ways are:

  1. Learn “pure” vi/vim, then introduce vimrc options and then plugins
  2. Start with an existing “customization” (from someone else), then learn what things do

Once upon a time, I would have suggested learning the basic features of vim before getting into customization, but there are quite a lot of people who are not interested in learning the tool unless they can be productive straight away.
When coming from an IDE, the apparent shortcomings of a less integrated text editor will scare them away before they have discovered the power of editing text with vim.

This guide is aimed at those people. I want to outline some steps to learn vim that makes the transition from IDE to vim as easy as possible with the hope of making vim a less scary step.

Installing Vim

Most systems will come with a version of vim, but you may want to get the latest version from the systems package manager for a more complete feature set.

On a mac, the standard install of vim is missing clipboard support so I would recommend installing MacVim, here is how I do it with homebrew:

1
2
brew install macvim
brew linkapps

This package provides mvim on the command line, but vim will still refer to the system version, so I setup a couple of aliases in my .bash_profile:

1
2
alias vim="mvim -v"
alias vi="vim"

Basic Usage

This guide is more about setting up vim in a manner that won’t seem too crippling when coming from an IDE, so I won’t focus too much on editing effectively with vim here.

If vim is completely new to you and you don’t know the basics such as the difference between command mode and insert mode or how to quit vim, I would recommend pausing the guide here and running vimtutor in your terminal to learn the basics.

Configuring Vim

Vim uses a .vimrc configuration file in your home directory. There is a plethora of configuration options you can put here, but I thought I would offer some basic options to get you started.

My .vimrc is quite large, but here is a snippet for some basic options that you can put into your own .vimrc to get started:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
filetype plugin indent on
syntax on

set ts=2 sw=2         " Use 2 spaces for tabs
set expandtab         " Use spaces instead of tab characters
set wrap              " Wrap the display lines (not actual text)
set linebreak
set backspace=indent,eol,start
set incsearch         " Show matching search results as typing
set ruler             " Show row and column in status bar
set wildmenu          " Nicer tab completion for :ex commands
set ignorecase        " Case insensitive search by default
set smartcase         " Use case sensitive search in a capital letter is used
set warn              " Show what mode your in (insert, etc.)
set scrolloff=3       " Number of lines to always show at at the top and bottom
set autoindent        " Copy the indentation from the previous line
set colorcolumn=81    " Highlight the 81st column (shorthand = :set cc=81)
set cursorline        " Highlight the line which the cursor is on
set laststatus=2      " Always show a status bar
set mouse=a           " Make the mouse work - even in terminals
set list              " Show `listchars` characters
set listchars=tab:=»,trail:·

" Easier way to copy and paste from the global clipboard
map <leader>p "+p
map <leader>y "+y

Navigating code

Vim has builtin support for ctags, which indexes your code and allows you to jump to the definition of a method or class. As usual, on a mac you will have a standard version of ctags installed, but it’s not very good, so I recommend installing the exuberant ctags package from homebrew:

1
2
3
brew install ctags
sudo mv /usr/bin/ctags{,-bsd}
sudo ln -s /usr/local/Cellar/ctags/5.8/bin/ctags /usr/bin/ctags

To make use of ctags, in the root of a project run the following command:

1
ctags -R .

This will need to be run when the code changes to keep the tags file up to date, so I have setup git hooks to automate this. If you don’t want to setup git hooks, you can execute this command from within vim with :!ctags -R .

Now if you open some code, move your cursor over an occurrence of a method or class, you can jump into the definition of that method or class with the following key bindings:

crtl + ] = Jump to definition (of what is under the cursor)
crtl + T = Jump back from following a tag

The following key bindings are also useful for navigation and do not require ctags:

/foo = Search for foo
* = Search for the word under the cursor
n = Jump to the next occurrence of the search
N = Jump to the previous occurrence of the search
crtl + o = Go back from the last jump
crtl + i = Go forward to the recent jump

Vim Plugins

Vim has a plugin system, but by default it does not do a good job of keeping plugins isolated from each other. To improve this, there are plugins that manage plugins.
I recommend using Vundle, here is how to set it up along with a few useful vim plugins:

1
git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle

Then place the following at the top of your .vimrc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
filetype off
set rtp+=~/.vim/bundle/vundle/
call vundle#rc()

Plugin 'gmarik/vundle'
Plugin 'kien/ctrlp.vim'
Plugin 'scrooloose/nerdtree'
Plugin 'tpope/vim-rails'
Plugin 'tpope/vim-rake'
Plugin 'tpope/vim-fugitive'
Plugin 'tpope/vim-commentary'
Plugin 'tpope/vim-repeat'
Plugin 'tpope/vim-surround'
Plugin 'vim-scripts/matchit.zip'
Plugin 'scrooloose/syntastic'
Plugin 'bogado/file-line'

call vundle#end()
filetype plugin indent on

Then, I choose configure some of those plugins towards the bottom of the .vimrc like this:

1
2
3
4
5
6
7
8
9
10
11
12
" NERDTREE PLUGIN - (mnemonic: Files)
nmap <leader>f :NERDTreeToggle<CR>
nmap <leader>F :NERDTreeFind<CR>

" CTRL-P PLUGIN
let g:ctrlp_user_command = {
\   'types': {
\     1: ['.git/', 'cd %s && git ls-files'],
\     2: ['.hg/', 'hg --cwd %s locate -I .'],
\   },
\   'fallback': 'find %s -type f'
\ }

Now, from within vim, run :BundleInstall

Next steps

At this point, you should have a somewhat powerful installation of vim, the next step is to learn how to use this power. Below are some resources to help you learn how to use vim effectively.