Git Shell Tools

Although i work in a nice and fancy IDE with all bells and whistles i ever need. I still do a lot of my day to day work in a shell. One of those things is working with Git.

To make git more fun to work with on the command-line. There are a couple of things i did.

Let’s start with auto-complete. It’s great to be able to tab complete branch names, remote files and tree and file paths. To make this happen we only need to download the following bash script from the people at Github.

$ cd ~/bin
$ wget

And to make this work in your shell add this to your .bashrc or .bash_profile

$ vi .bash_profile
if [ -f ~/bin/git-completion.bash ]; then
    source ~/bin/git-completion.bash

The only thing we need to do to make TAB completion work is reload the bash profile. We can do this by sourcing the file.

$ source ~/.bash_profile

Another fancy addition to working with git in a shell environment is something my coworkers showed me. It’s called the git-prompt. And is also created by the people at Github.

This script will do a couple of things. One of them is displaying which the current working branch is. More visible enhancements are possible by populating certain variables.

GIT_PS1_SHOWDIRTYSTATE Use the ‘*’ and ‘+’ characters to display unstaged and staged changes

GIT_PS1_SHOWSTASHSTATE Use ‘$’ to display stashed changes

GIT_PS1_SHOWUNTRACKEDFILES Will use ‘%’ to display there are untracked files

And more settings are possible. Check the readme at the beginning of the script for this. But what the script actually does is use the shells PS1 variable to display previously mentioned visible enhancements.

So let’s start by fetching the actual script

$ cd ~/bin
$ wget

Now that we have the script in place. Lets update the bash profile

if [ -f ~/bin/ ]; then
   source ~/bin/
   export PS1='\[\e[31;1m\]\u\[\e[0m\]\[\e[37;1m\]@\[\e[0m\]\[\e[36;1m\]\h\[\e[0m\]$(__git_ps1 " \[\e[32;1m\][%s]\[\e[0m\]") \[\e[37;1m\]$\[\e[0m\] ' 

In this case my PS1 is a bit more fancy because of the added colors. But the magic comes from adding

$(__git_ps1 "[%s]")

When the profile is sourced once again. You can see what happens when we move to a repository

$ cd path/to/git/repository
username@hostname [branch-name *] $

The scripts used in this post can be found in this repository

Run Composer on Git Clone

I work on a couple of projects that use Composer to manage the dependencies. And a coworker asked if it was possible to automate running composer install after cloning a repo. It sounded like a good idea. As i sometimes forget to run the command myself. So i did some research. And it turned out to be quite easy.

To makee this work we will be using Git hooks together with Git templates.

So we start by creating a templates folder for git. Where does not matter.

$ mkdir -p [full path]/git-templates/hooks

When that’s done. we need to tell git to use the template folder on each clone / checkout. We can do this by setting a global alias for clone

$ git config --global alias.clone 'clone --template=[full path]/git-templates'

You can also do this by manually editing the .gitconfig file

clone = clone –template=[full path]/git-templates

So now we have a template folder that’s read on every clone / checkout. We only need to create the hook script that triggers composer.

$ vi [full path]/hooks/post-checkout
#! /bin/bash
# Check if a composer.json file is present
function composer_run() {
    REPO=$(readlink -m $(dirname .))
    if [ -f $REPO/composer.json ]; then
        composer install


Finally wer need to make it executable

$ chmod +x [full path]/hooks/post-checkout

Let’s test it by cloning a test repo

$ git clone foo

Cloning into foo…
remote: Counting objects: 21, done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 21 (delta 5), reused 14 (delta 1)
Receiving objects: 100% (21/21), done.
Resolving deltas: 100% (5/5), done.
Loading composer repositories with package information
Installing dependencies (including require-dev)
- Installing psr/log (1.0.0)
Loading from cache

- Installing monolog/monolog (1.12.0)
Loading from cache

Octopress Blog Hijacked

I use Octopress to write and generate my blog. Which works pretty well most of the time. The main benefit is having a statically generated website. No database connections no code overhead. Just plain and simple text. You’d pretty much have to 0wn the server to get to the files.

To my surprise though my blog was redirecting to when i check my blog status today. That was pretty weird. So the first thing i did was check my commit logs. No changes. Github didn’t get owned (at least not publicly known). So what could be redirecting my site?

So i grepped for the domain name i was redirected to.

$ grep -r 'octophile' *

All generated pages had a call to This came from the main layout template. And was there from the start. So what was it for. I just couldn’t remember. But a quick Google search turned up the Github project page. It’s the twitter widget i used for a while. Still weird though. So let’s check the contents of the widget.js file

var redir_url = ''; if (window != top) { top.location.href = redir_url; } else { window.location = redir_url; }

OK that explains the redirect. Now let’s take a look the WHOIS data for the octophile domain

   Domain Name: OCTOPHILE.COM
   Sponsoring Registrar IANA ID: 1200
   Whois Server:
   Referral URL:
   Name Server: 70222-NS1.NDOVERDRIVE.COM
   Name Server: 70222-NS2.NDOVERDRIVE.COM
   Status: clientTransferProhibited
   Updated Date: 05-feb-2015
   Creation Date: 30-jan-2014
   Expiration Date: 30-jan-2016

So the DNS was changed yesterday. It might be somebody hijacked the domain. But i’m not sure. Maybe the project is just discontinued. Whatever it is. It was fun to figure out what was going on. I contacted the owner of the widget. But haven’t received a reply yet.


I got a quick response from the project owner. He stopped working on it a long time ago. And i probably should have cleaned up my templates. Good thing no evil javascript was injected :)

Using the Hub in Github - Pull Requests

Hub is a command line tool that wraps around the git command. It add’s some cool features that make working with git easier. The goal of this post is to show how easy it is to generate a pull request. But i’ll also quickly explain how to install hub itself.

Hub is written in Go! So we need to install this to get started. You can download the latest package/source here

$ sudo tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz
$ vi ~/.bashrc

export PATH=$PATH:/usr/local/go/bin

With that in place we can setup hub

$ git clone
$ cd hub
$ ./script/build
$ cp hub /usr/local/bin
$ hub --version

git version 1.9.1
hub version 2.2.0-rc1-13-g111100c

If you are used to the git command like me. It might be a good idea to setup a alias for hub

$ vi ~/.bashrc

alias git=hub

One other thing i had to do because we work with the Github Enterprise Edition. Is to whtelist our github host.

$ git config --global --add github.dome.domain

Creating a pull request with hub is as easy as using the Github web gui. We start of with creating a fork of an existing repository

$ git clone git@github.some.domain:user/FOO.git
$ cd FOO
$ git fork

This created the remote fork. And sets the correct remotes for the local repository

$ git remote -v

origin git@github.some.domain:user/FOO.git (fetch)
origin git@github.some.domain:user/FOO.git (push)
me git@github.some.domain:me/FOO.git (fetch)
me git@github.some.domain:me/FOO.git (push)

Before we can generate a pull request we ofcourse need some changes to push.

$ git branch bar
$ git checkout bar
$ touch BAR
$ git add BAR
$ git commit -am "Add BAR"
$ git push me bar

Total 0 (delta 0), reused 0 (delta 0)
To git@github.some.domain:me/FOO.git
* [new branch] bar -> bar

The only thing left to do is create the actual pull-request

$ git pull-request


View Unpushed Changes in Git

When focus shifts to other projects. It might happen that some repository sits around for a while without being worked on. And if getting your forked repository synced isn’t a big enough problem. It might contain some unpushed changes. So this happened the other day at the office.

$ git status

# On branch master
# Your branch is ahead of ‘origin/master’ by 16 commits.
nothing to commit (working directory clean)

Doing a simpel push would resolve the problem. But what if some changes are not needed anymore. Or some other spec changes that allow for some further inspection. So it might be a good idea to inspect the changes before we push them to remote. And thankfully git makes this quite easy. By diffing the HEAD against remote master.

$ git diff origin/master..HEAD

diff –git a/path/library/init.php b/path/library/init.php
index 0c5ae45..50a2060 100644
— a/path/library/init.php
+++ b/path/library/init.php
@@ -8,13 +8,6 @@
* directory structure.

-function FOO_library_autoloader( $classname )
- $classfile = str_replace(“_”, “/”, $classname) . ‘.php’;
- if (file_exists(LIBRARY . $classfile))
- require_once(LIBRARY. $classfile);

And voila. A diff of all unpushed changes. This also works for upstream repository’s. But the code has to fetched first. So before running the diff command. Do this

$ git fetch upstream master
$ git diff upstream/master..HEAD

Secure Cloud Storage With Google and Encfs on Ubuntu

Before we start let me say that I am not a big fan of storing private data in the cloud. And even if you do there might be better solutions to protect your data then what i will describe here.

I’ve chosen to use Google drive for this example. So there will be some Google drive specifics. But this should work with practically any cloud storage provider.

First you are going to have to have a application available that can mount your cloud storage as a local resource. I have chosen to use Insync. But you could use something like Grive instead.

Setup EncFS:

$ sudo apt-get install encfs

Install a cloud sync tool:

$ sudo dpkg -i insync_1.0.32.31767-trusty_amd64.deb

When the initial sync is done we have all the ingredients ready. So it’s time to create some encrypted space inside the cloud container. No need to create a directory because encfs will do this as well.

$ encfs ~/[some-path]/[user]/encrypted ~/Private

Store the encryption key in a save place. And we are done with the encryption part. The only thing to do is setup auto mounting.

$ hg clone
$ cd gnome-encfs
$ sudo install gnome-encfs /usr/local/bin
$ gnome-encfs -a ~/[some-path]/[user]/encrypted ~/Private

Get the First Weekday of the Month in PHP

A simple method to return the first weekdsay of a given month and year

private function _getFirstWeekdayInMonth($month, $year, $day = 1) 
    $dateData = getdate(mktime(null, null, null, $month, $day, $year));
    if (in_array($dateData['wday'], range(1, 5))) {
        return $dateData['mday'];
    return $this->_getFirstWeekdayInMonth($month, $year, ($day+1));

$wday = $this->_getFirstWeekdayInMonth(11, 2013);

Renaming a Folder in Git That Contains Submodules

Because of some project structure changes. It was required to renamed some folders. In git this should be as easy as running git mv. But when the folders you are trying to move contain submodules. Its a whole different story.

$ git mv old/ new

fatal: source directory is empty, source=old/cookbooks/apache2, destination=new/cookbooks/apache2

Like i said. This seems to work for normal folders. But submodules are a bit more complicated because of paths set in various files. So let’s try just moving them on the filesystem.

$ mv old/ new
$ git status

# deleted: old/VVagrantfile.example
# deleted: old/cookbooks/apache2
# deleted: old/cookbooks/apt
# deleted: old/cookbooks/beanstalkd/.travis.yml

That’s not what we’re looking for. We want to move the files. Not remove them. At this point i was at a loss and spend some time looking around stackoverflow. Which has multiple solutions available from other developers. But none seemed to fit the bill. So i ended up combining a couple.

First create the new location and add it to the git index.

$ mkdir new
$ git add new

In my case i had normal folders and submodules in the same directory. So first i moved the normal folders to the new structure.

$ git mv old/[some folder] /new

Now it’s time for the submodules. We need to update the paths in each submodule’s .git file. And the paths in project .gitmodule file

$ find . -name .git -type f -print0 -type f | xargs -0 sed -i 's|old|new|g'
$ find . -name .gitmodule -type f -print0 -type f | xargs -0 sed -i 's|old|new|g'

After that add the .gitmodule file to the git index and checkout the status

$ git add .gitmodule
$ git status 

fatal: Could not chdir to ‘../../../../../new/cookbooks/apache2’: No such file or directory
fatal: ‘git status –porcelain’ failed in submodule old/cookbooks/apache2

So we’re not there yet. As it turns out the git config file also contains the submodule paths. And the .git/modules folder contains a submodule mapping as well. So let’s fix that

$ find . -name config -print0 -type f | xargs -0 sed -i 's|old|new|g'
$ mv .git/modules/old .git/modules/new
$ git status

That looks good

modified: .gitmodules
# renamed: old/Vagrantfile.example -> new/Vagrantfile.example
# renamed: old/cookbooks/apache2 -> new/cookbooks/apache2
# renamed: old/cookbooks/apt -> new/cookbooks/apt
# renamed: old/cookbooks/beanstalkd/.travis.yml -> new/cookbooks/beanstalkd/.travis.yml

Now we can remove the old folder from the git project and commit the changes.

$ git rm -r --cached old/
$ git commit -a -m "Moved old to new folder"
$ git push

Fixing the Clover Forcast for PHP Projects in Jenkins

I had the opportunity to play with Jenkins again last week. And the setup for our projects went pretty smooth. But the fact that no matter what i tried. The clover forecast icon would always show up as rainy . While the build was succeeding without issues. So i spend some time googling and trying out multiple “fixes”. Of which none seemed to actually work. I even reverted back to using the Jenkins clover plugins instead of Clover for PHP. No difference at all.

It seemed as if the settings from the config page were completely ignored when calculating the clover status. This was really bugging me. So i checked out the clover plugin source from github. And browsed through the code for a while. When i found the beauty below inside

public Set<CoverageMetric> getFailingMetrics(AbstractClassMetrics coverage) {
    Set<CoverageMetric> result = new HashSet<CoverageMetric>();

    if (methodCoverage != null && coverage.getMethodCoverage().getPercentage() < methodCoverage) {

    if (statementCoverage != null && coverage.getStatementCoverage().getPercentage() < statementCoverage) {

    if (elementCoverage != null && coverage.getElementCoverage().getPercentage() < elementCoverage) {

    return result;

So it seems as if somewhere in the plugin it’s actually calculating the average of the coverage per setting. The strange thing in the method above however is the elementCoverage setting. Which is not available in the Jenkins config interface. And causes issues because we have no influence over this setting.

So i added the setting to the config manually

$ vi /var/lib/jenkins/jobs/[project]/config.xml

<org.jenkinsci.plugins.cloverphp.CloverPHPPublisher plugin="cloverphp@0.3.3">

And voilà. I nice sunny forecast. Now let’s see if i have some time to write a patch for this.

Github, SSH and Multiple Repositories

When working with Github. Setting up SSH key based authentication is easy. You just create a key. Add the public key in the admin panel and voilà. If a new contributor joins your team. You add his / her key and they also have access.

But how does it work when you have need access to multiple repositories using multiple keys yourself? I had to set this up a couple of times. And it turns out to be just as easy. But if for some reason it’s not that obvious these steps might help.

Let’s pretend we need some key first.

$ ssh-keygen -t rsa -b 4096

Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): repo1_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

Your identification has been saved in repo1_rsa.
Your public key has been saved in
The key fingerprint is:
03:b5:da:08:3b:6f:9a:29:3f:f5:4c:ee:5d:14:cb:41 user@host
The key’s randomart image is:
+–[ RSA 4096]—-+
some output

This will generate the public and private key for repo1. Now repeat the same thing for repo2. Make sure the keys reside in ~/.ssh

Now let’s say we have access to two repositories under two different users / companies. We will use and as examples. The only thing we have to do is add some entries to ~/.ssh/config to make this work. They key is to use the Github sub-domain mappings

$ vi ~/.ssh/config

    PreferredAuthentications publickey
    IdentityFile ~/.ssh/repo1_rsa

    PreferredAuthentications publickey
    IdentityFile ~/.ssh/repo2_rsa

Save the file and we’re done. Now to checkout a project in one of the repositories. Do the following.

$ git clone

Cloning into ‘project’…
remote: Counting objects: 86, done.
remote: Compressing objects: 100% (66/66), done.
remote: Total 86 (delta 27), reused 64 (delta 17)
Receiving objects: 100% (86/86), 34.83 KiB, done.
Resolving deltas: 100% (27/27), done.

Copyright © 2015 - Thijs Lensselink - Powered by Octopress