Simplify your workflow with Git Aliases

Git is a great tool.

When using it from the command line (which I would recommend to everyone) there can be a lot to remember.

As with everything, I like to customise how I work and Git is no exception.

Adding a git alias is a simple process.

From your terminal/Powershell type:
git config --global alias.{alias} {git command}

Below are the aliases I use on a daily basis which really speed up my workflow:

git config --global alias.s status
git config --global alias.l log
git config --global alias.lo log --oneline
git config --global commit -m
git config --global checkout development
git config --global checkout
git config --global alias.ap add -p
git config --global alias.rhh reset HEAD --hard
git config --global alias.rcb rebase -i
git config --global alias.rlt rebase -i HEAD~10
git config --global alias.pick cherry-pick
git config --global alias.ka gitk --all

If you are having trouble with Folder Redirection in Windows, you can copy these aliases into the local config of the git project: ./{gitProject}/.git/config, under the [alias] section:

s = status
l = log
lo = log --oneline
cm = commit -m
cd = checkout development
co = checkout
ap = add -p
rhh = reset HEAD --hard
rcb = rebase -i
rlt = rebase -i HEAD~10
pick = cherry-pick
ka = gitk --all

Vim Keys in Visual Studio

Anyone who writes applications on the Windows platform will likely spend most of their time in Visual Studio.

Although I find Visual Studio is pretty bloated, it ends up being a necessity when working with clients as it’s a tool the rest of their team will be used to.

To make Visual Studio more friendly to Vim users there is a plugin called VSVim which is available in the market place:
VsVim – Visual Studio Marketplace

Below is the config I’ve been using for over a year and really makes using Visual Studio a much nicer experience.

I’ve tried to group the features and really like using , as the leader key, especially when using the Halmak keyboard layout.

Happy Vimming!!

" Navigation
nnoremap ,. :vsc View.QuickActionsForPosition
nnoremap ,, :vsc Edit.GoToAll
nnoremap ,g :vsc Edit.GoToImplementation
nnoremap ,d :vsc Edit.GoToDefinition
nnoremap ,f :vsc Edit.FindAllReferences
nnoremap ,mn :vsc View.NavigateForward
nnoremap ,mp :vsc View.NavigateBackward
nnoremap ,mm :vsc View.NavigateBackward

nnoremap ,s :vsc File.SaveAll
nnoremap ,x :vsc File.Close

" Errors - ,eX
nnoremap ,ee :vsc View.ErrorList
nnoremap ,en :vsc View.NextError
nnoremap ,ep :vsc View.PreviousError

" Refactoring - ,rX
nnoremap ,ri :vsc Refactor.ExtractInterface
nnoremap ,rr :vsc Refactor.Rename
nnoremap ,rf :vsc Edit.FormatDocument
" comment isn't working
nnoremap ,cc :vsc Edit.ToggleBlockComment
"nnoremap ,cc :vsc Edit.ToggleLineComment

" Tests - ,tX
nnoremap ,ta :vsc TestExplorer.RunAllTests
nnoremap ,tt :vsc TestExplorer.RunAllTestsInContext
nnoremap ,tc :vsc TestExplorer.RunAllTestsInContext
nnoremap ,ts :vsc TestExplorer.RunSelectedTests
nnoremap ,td :vsc TestExplorer.DebugAllTestsInContext
nnoremap ,tf :vsc TestExplorer.RunFailedTests

" Build - ,bX
nnoremap ,bb :vsc Build.BuildSolution
nnoremap ,bc :vsc Build.CleanSolution
nnoremap ,br :vsc Build.RebuildSolution
nnoremap ,bd :vsc Debug.Start
nnoremap ,bw :vsc Debug.StartWithoutDebugging
nnoremap ,bq :vsc Debug.StopDebugging

" Window - ,wX
nnoremap ,wn :vsc Window.NextTab
nnoremap ,wp :vsc Window.PreviousTab
nnoremap ,ww :vsc Window.MoveToMainDocumentGroup
nnoremap ,wa :vsc File.CloseAllButThis
nnoremap ,w/ :vsc Window.NewVerticalTabGroup
nnoremap ,wd :vsc Window.CloseDocumentGroup
nnoremap ,wh :vsc Window.MovetoPreviousTabGroup
nnoremap ,wl :vsc Window.MovetoNextTabGroup
nnoremap ,' :vsc Window.NextDocumentWindowNav

" Ncrunch - ,nX
nnoremap ,nn :vsc NCrunch.GotoNextBuildorTestFailure
nnoremap ,nh :vsc NCrunch.HotSpots
nnoremap ,nm :vsc NCrunch.Metrics
nnoremap ,na :vsc NCrunch.RunAllTestsRightNow
nnoremap ,ns :vsc NCrunch.Showcoveringtests
nnoremap ,np :vsc NCrunch.PincoveringteststoTestsWindow
nnoremap ,nu :vsc NCrunch.UnpincoveringtestsfromTestsWindow
" nnoremap ,nu :vsc NCrunch.UnpinalltestsfromTestsWindow

nnoremap ' `

Concatenating files in Powershell

When working with databases, it’s best practice to create migration scripts to which apply your database changes, rather than using GUI/designer tools which need you to manually apply changes across multiple environments.

I’ve been working with a client where there isn’t a specific migration tool to run all these migration files at the end of project, but they need to be bundled into a single file and attached to the change tracking system.

I keep these files under version control and prefix migration files with M_ and rollback files with R_

In Bash concatenating these files is simple:
cat M_* > ./migration.sql

In Powershell it isn’t too different:
Get-Content M_* | Set-Content .\migration.sql

When dealing with rollback scripts I create the rollback which opposes the migration with the same number which makes the files easy to navigate:


Rollback scripts are slightly more interesting as they need to be run in reverse.

We can also achieve this in Powershell with a minor tweak to our previous command:
Get-Content R_* | Sort-Object -Property Name -Descending | Get-Content | Set-Content .\migration.sql

This will firstly get all our rollback files and then reverses the order, then gets the content of each file and writes it to a single file.

Although I prefer doing these types of tasks with Bash, it’s still quite easy to remember the Powershell commands if you don’t have access to Bash on a Windows system.

Using a Dual Shock 3 controller with Steam on Linux via bluetooth

I was really surprised as to how easy this ended up being.


Open up your favourite terminal, and type bluetoothctl.

Next connect your controller by USB and you should be prompted as to whether you trust the device, type ‘yes’.

Disconnect the USB cable and press the PS button on the controller.

After a few flashes of the leds it should pair successfully.

You can repeat the above procedure for additional controllers as required.


The next problem is how to disconnect the controller without needing to turn off bluetooth or power off your computer.

Back to the terminal and a simple command will disconnect all connected controllers, saving your precious battery.

bluetoothctl devices | awk '{print $2'} | xargs -I{} bluetoothctl disconnect {}

Let’s break this down.


bluetoothctl devices will list all connected devices

All we care about is the id of the controller so piping the output to awk we can map only second element (the id).

Next pipe the id’s back to the bluetoothctl command and disconnect the controller.

Nice and easy and you could even map this command to keyboard shortcut. I’ve simply created a bash alias, ds3disconnect to save my fingers.

Steam should detect the controller without a hitch and you can get some wireless Session flip trick goodness.

Inlining Js and Css files in ASP.Net MVC View

As part of testing the performance of some views I’ve been working on recently I kept seeing the following warning in the Chrome Dev tools:

"[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check",

When creating new views I’d created my “Components” in as 3 separate files: Component.cshtml, Component.js, Component.css. These were then being included with either link or script tags in the .cshtml file for the partial view. This is something I have become used to when working with Angular so it feels wrong to throw everything in one file.

All my $.ajax requests in the .js files were async (as they are by default so it had to be the import.

As Chrome was correctly identifying, including the files in this way wasn’t optimal, but what was the alternative?


Now this approach might still not be ideal, but I didn’t want to add any additional steps to the existing build process or include any extra dependencies and make it simple for other developers to use in their own code, so the first step was to get the scripts content into the .cshtml.

A simple solution was to use the answer from this SO question.

First create a extension method which reads the text from the path provided, and then return it as a HtmlString so it is included on the page.


public static class HtmlHelperExtensions
    public static MvcHtmlString InlineScriptBlock<TModel>(this HtmlHelper<TModel> htmlHelper, string path)
        var builder = new TagBuilder("script");
        builder.Attributes.Add("type", "text/javascript");

        var physicalPath = htmlHelper.ViewContext.RequestContext.HttpContext.Server.MapPath(path);
        if (File.Exists(physicalPath))
            builder.InnerHtml = File.ReadAllText(physicalPath);

        return MvcHtmlString.Create(builder.ToString());

This can then be used in a view file in place of the script import:



<p>This view doesn't do much yet!</p>

Applying these changes to my code caused the error to go away, but it still felt like it needed improving, as no modifications were being made to the included javascript, it still contained unnecessary whitespace and could be made smaller. This will be covered in the next post about bundling.

Unable to access Puppet Learn from VM in VirtualBox

Puppet is an open-source automation platform designed to help automate software deployments and management of IT Infrastructure.

Helpfully, they have a VM which acts as a “a self-contained learning environment” so you can get to grips with what is possible.

After Downloading the VM from here, extracting the contents of the zip file and starting it in VirtualBox I was presented with the following screen.

Trying to access the IP listed here didn’t work.

The fix was to shutdown the VM, open the Settings in VirtualBox and update the Network > Adapter > “Attached To” value from “NAT” to “Bridged”.

After starting the VM again, the IP address had been updated to, which was accessible through a browser and I could continue with the guide.


Funnily enough, slightly further down the Puppet documentation it lists the above as a solution.

Puppet Adapter Bridged Configuration

At least if the documentation wasn’t so thorough, I’d have been able to easily sort this issue.