Use different Git Diff Tools Per File Extension

How to setup git to allow different merge/diff tools based on file extension.

I'm going to put this here so I can find it later…

Create a merge-wrapper script

To allow us the flexibility we want to determine which diff tool should be used for different file extensions, we need to break out the logic in to an external script. Below I have 2 samples of a merge script. I started with the .sh file (bottom), but changed over to the .js version (above that) since it is easier for me to maintain.

I haven't yet tried to run this on windows, but suspect we can wrap the merge-wrapper.js in a .cmd file calling it with Node.JS.

Customize the merge-wrapper.js

  1. Extend with other diff tool support:

    If you want to extend the script to add support for your own diff tool, just create a new function that returns an object following the pattern of the existing createP4MergeCommand or createOpenDiffCommand.

  2. Modify which diff tool is used per extension:

    If you want to change which tool is used per file extensions you can modify the diffLookup hash to map various extensions to whatever tool you setup.

  3. Leave me a comment (either here – or in the gist) of what diff tool you added.

    I'd be happy to take contributions of other diff tools in this gist if you leave a comment with yours…

Below was an attempt at using a bash script to manage what I do above, it'll work for some, but I didn't want to maintain this – prefer the JS version instead.

Setup ~/.gitconfig

Now that we've created our merge wrapper script we need to tell git how to use it.

Say we placed our merge script in the following directory: $HOME/dotfiles/tools/merge-wrapper.js. You can add the below to your ~/.gitconfig file and when you use git difftool our new merge-wrapper will be used to pick diff tools based on file extension.

[merge]
    tool = merge_wrapper
[mergetool "merge_wrapper"]
    cmd = $HOME/dotfiles/tools/merge-wrapper.js "$BASE" "$LOCAL" "$REMOTE" "$MERGED"

Introducing SkypeIt – Command Line Skype Phone Calls

SkypeIt

In short npm install -g skypeit and enjoy quickly jumping on conference calls.

What is it?

A simple little command line utility that can be used to efficiently jump on a conference call and automatically dials the extension or conference ID.

What pain does this solve?

I've recently been working on a number of projects where often times more than twice a day I have to jump on a conference bridge.

This typically involves:

  1. Opening the Outlook appointment
  2. Copying just the conference phone number (without extension)
  3. Pasting it in Skype to dial
  4. While Skype is dialing, I go back to Outlook and copy the extension/conference id.
  5. Pasting in Skype's number pad area
  6. Type or use the mouse to press the final # key.

How does SkypeIt improve this?

SkypeIt takes the 6 steps and cuts them in half or more.

  1. Open the Outlook appointment
  2. Copy the conference phone number & extension (if there is one) in one shot.
  3. At the (already open command line – because we developers usually have a command line open) paste in skypeit "<paste here>" <press enter>

The problem this solves may seem like a first world problem, but a big annoyance factor when running through the original steps to get on a conference call is, people who setup these meetings, rarely include the final # sign needed at the end of a conference ID/extension #. So when I paste the extension into Skype, I still have to manually get the # in there.

SkypeIt even better with teams!

If you work remotely as I do, then you're probably communicating through things like HipChat, Skype, Slack, AOL (I-kid, I-kid), etc. Instead of I.M.ing your team to remind them to jump on a call where they would have to repeat the long steps above, you can just paste the skypeIt ###-###-### ###### command necessary to immediately jump on a call. This serves to remind them a call is coming up or already started and saves time from having to find the number/extension as they can copy/paste it directly at the command line.

Or even better, if you're on a Mac and using ZSH at the command line, SkypeIt has tab completion support and a YAML config strategy, so you can easily configure a project with your standard phone numbers (say daily standup conference number) and check in a .skypeitrc file to the project. When you're in the context of the project you can just type skypeit stand<tab> and jump on your daily standup conference call.

Does anyone who works remotely actually stand-up on a daily standup call? hmmm…

Still early…

SkypeIt was written to solve a personal pain-point and is not yet a complete solution for all conference call situations. If you'd like to see your scenario supported, head on over to the SkypeIt Issues on GitHub and drop me a line.

I'm not currently using a windows machine – but with the windows protocol activation capabilities, we can probably easily add support for windows to SkypeIt.

Manage Work Item Tags in Visual Studio

Visual Studio customers have been asking for richer tagging features inside the IDE for a long time. TFS and VSO have allowed tagging of work items for well over a year, but the only way to really work with the tags has been through the web interfaces.

The teams that build features in Visual Studio have a LOT of things in their backlog (I can attest to this as I was one for a little while). Adding tag management features to VS would be fairly far down that backlog, but luckily a community project has just shipped its first release of a plugin for VS that allows management of tags if you are working with TFS or VSO.

This is thanks to the ALM Rangers, who are basically a group of volunteers who provided patterns&practices style guidance for ALM tooling issues in the Microsoft tool stack.

Tag Admin for VS 2015 only works with VS 2015 Preview builds at this time, but it sounds like work is underway to support current (older versions).

Here’s a demo

Tag Management in Visual Studio

 

I know the fact that this only works with Visual Studio 2015 is a bummer for most of us, but keep watching the project. Backlog is being transformed to Increments, I’m told Smile.

Charging Station – I Apparently do Handicrafts Now

I regret not having blogged in several months and am determined to get back on that wagon. Let’s start simply, with a goofy little holiday project.

This is what happens when my boss puts me on “you’ve been working too much” leave. I do dumb things in the garage.

I despise an untidy mess and tangle of wires. I could easily work atop a dirt floor with a half inch of dust on things, so long as all things in the room are at right angles to one another and there isn’t a knot of wires in sight. I know, it’s my own little OCD problem.

Accordingly, I recently came up with a Pinterest-worthy handicraft that hides all my tangled charging cables. I grew tired of seeing tangles of micro-USB cables flowing from powers strips, so here is my solution.

image

At a friends recommendation, I bought an Anker IQ charging brick. You can get a pack o’ cheap and short micro-USB cables with it for $10 more.

Then I took a wooden cigar box, secured from my local cigar shop, and drilled holes in it to support the power cord and up to 6 micro-USB cables poking out the sides. I velcroed the charger to the inside of the box so it wouldn’t knock around in there when I move the box.

image

It looks a bit like an insect.

image

But it works great and when I am not charging anything, I can push the cables back into the cigar box. Nice and tidy.

image

Thoughts on Working Remotely from Home

This post may seem a bit longer than my usual posts. It's one I've slowly been extending over the last couple years while working remotely. Many of the points may be obvious ones, but if you're considering a work-from-home (remotely) type of position that you consider some of these topics.

Background

My previous job afforded me the opportunity to work from home a couple days out of the week. While putting my wife through school, those days were great. I would start work extra early so I could leave early and watch our little girl while my wife headed off to class. The early start was great because these quiet mornings were often the most productive part of my day. The lack of distractions such as email, meetings, and instant message chats along with the quiet focus time all contributed to this increased productivity.

While I quite enjoyed this time, was often productive, and it helped my family I still preferred to go into the office over working from home.

So why did I still prefer going to the office over working from home?

I did not feel as connected to the group, which left me feeling as thought I was always playing catchup. All of those water-cooler discussions and inpromptu office meetings where I (or anyone else remote) wasn't pulled into more often not left me feeling like I was not able to keep on top of what was going on.

This experience and the feeling it left me with is what concerned me about the new job I was about to take.

Worried to take a remote / work from home job.

Given my limited work from home experience, I was concerned about working remotely 100% of the time. However, the new opportunity to work for a consulting firm I admired, and the thought of being able to constantly try new technologies, and business domains was really appealing.

I have now worked remotely for Vertigo for over 3 years and I'd like to share a list of Pros/Cons that I've gathered through my experience working from home full time.

Con's to working from home

Now, while Con's do not outweigh the Pro's for me, there is quite a bit of grey area here, so let's review some con's.

  • Less human/social interaction on a daily basis. As an introvert, and a software developer, this is generally not too bad. This was a bigger concern for me originally and is much less of an issue now that I've tried it out. I make sure to take some time to have great Skype video calls with fellow remote coworkers and I also try to offset this by participating in local user groups or and other social occasions. However, the best medicine for this is a simple trip to the park with my little girls. I will say that I've had a day or two where I jumped at the opportunity to take a trip to Costco or other errand just so I could get out of the house…
  • Shipping Hardware.
    • This one is a bit of a pain. Working for a consulting firm means there are many of different projects that require varying hardware configurations. From Xboxes, test phones, tablets, computers, and even TVs. I semi-regularly run to FedEx and send something to H.Q. or the Apple Store or Best Buy to pick up some hardware based on the needs of a project.
  • It can be a little too easy to sit at the personal computer in the evening and reach over to my work computer to reply to a late work-related email, or hammer on some code. So you need to be careful about the work/family balance when it's so easy to work from home. This takes a bit of discipline.
  • Sitting in the office chair when the amazingly yummy aromas of some fresh home cooking – distracting me from being productive as the smell is driving my stomach to scream at me to go downstairs for some food!
  • Communication
    • Being remote, you have to become an over-communicator. An email here and there is fine, but combine that with chat/I.M., phone calls, video chat calls (preferred), and more emails. However, you have to work a little harder to be noticed, especially if you have to compete with people who are all working in the same office.
  • It often takes a little more discipline to take breaks.
  • Time Zones
    • Time Zones are a hassle from many different angles, even when you work at an office; however, working remotely often means your employer has hired you because you are not near them. This increases the chance that you are several or more timezones away from your company's headquarters. Which can mean the usual things like meal planning, start/stop times, etc require a bit more planning and accommodation.

Pro's to working from home

  • Home office temperature!
    • Like most indoor jobs, AC and Heat are good amenities to have, but in big buildings people cannot often control the temperature. It's either too cold or too hot as big buildings have a mind of their own (their airflow and ventilation kinks). However, working from home, you're the master of your indoor weather. If you get hot, take off some clothes or turn on the AC. If you're too cold, put on some clothes or crank up the heat.
  • Commute
    • I often joke with my fellow Californian commute ridden co-workers when they complain about traffic that day that I narrowly avoided a 3 (lego) car pile-up on my way to the office.
    • I live where it's cold in the winter and not having to scrape the ice off of the windshield of my car in the morning due to the icy dew is a HUGE benefit.
    • Plus there's the, well not commuting part. While I enjoyed using the commute to zone out to my favorite podcasts, I still find time to keep up with my podcast when doing things like laundry, dishes, etc.
  • More family time overall. Since my coffee, water, bathroom breaks all lead to opportunities where I can say hello to the family.
  • SWEATPANTS! My wife recently introduced me to sweatpants. OMG they are comfortable, try wearing those at the stuffy-formal-office…
  • Quiet place to focus. It's easy to isolate yourself from the outside world if you need some quiet time to focus and be productive. Shut off the I.M., put phone on do not disturb, close email and get some serious work done.
  • We have all the usual necessities at home,
    • Tools (for that time you need a screwdriver)
    • Easy access to hygiene related products/tools. Ever need to take a shower in the middle of the day? Change of clothes (spilled coffee….)? Or brush your teeth?
  • Invest in your office.
    • When you invest in your home office, you're investing in yourself. Get a good chair, desk, keyboard, mouse, etc.
  • Lunch at home. My wife is a great cook. I'm spoiled to nearly always have a great set of leftovers in the fridge. Keeping me from eating out all the time. Not having to worry about someone eating my leftover chicken-wings (ya, that really happened – not even funny – You know who you are!)
  • My wife just brought me the most amazing homemade burrito. I didn't even care I was on a video call with my team. nom…nom…nom…
  • One of my favorite perks, is not even a perk that any company could offer (or even replace). I take the opportunity to for 10-minute break in the afternoon, where I walk up the street to meet my daughter at the bus stop. This is so much more important in my life than practically any company can offer (like free lunches, ping-pong table, etc…).
  • Scheduling an at-home call is easy. It's rarely a problem to have a fix-it man come by, or cable-guy, or if a package needs to be signed for, working from home makes this easy.
  • David's Additions: I shared a draft of this post to a good friend and coworker and he gave me some other tips, I hadn't thought of, which I totally agree.
    • You struggle on problems and your kid walks in the room and puts your life in perspective.
    • I can listen to my music turned way up!

What about distractions?

I get this a lot, when I tell others I work from home. "I don't know how you don't get distracted with other things to do at home." This may be a very individual thing. While, there can be distractions at home, I've always been a focused individual and I would say it's often easier to be distracted at the office with office chit-chat, meetings, going out to lunch, etc.

Not-so socially appropriate

  • When you're at the office, possibly in a long meeting, what do you do if you have some gas? Working remotely, there's no stress, or stomach pain… Mute your conference call, relax and nobody is the wiser. (Except this one time, I did such a thing not realizing my wife was within an earshot. Yea, a bit embarrassing but we had a laugh over it.)

Updating git branches.

How to update a git branch OTHER than the one you're currently on.

git branch -f {branch-to-change} {commit-to-change-to}

I recently setup a C.I. server to automatically generate builds of an iOS application and upload to TestFlight. I don't want each and every push to master to trigger a new TestFlight build, so I configured my C.I. server to watch the release branch.

I was starting to dislike the switch branch dance to trigger a new build.

What I used to do:

# When I was on the master branch
git checkout release
git merge master
git push

When things start to hurt, look for a better alternative. And with Git, there is almost always a more efficient way.

After digging a bit, I found the answer.

git branch -f {branch-to-change} {commit-to-change-to}

So to trigger a new build from master I can just:

git branch -f release master
git push origin release

Or wrap that in a Gulp task gulp tf. And with CommandAllThings I can now type rake tf, or grunt tf or gulp tf and they all trigger a new build to come out of TestFlight.

Or if you wanted to skip moving your local branch, you could just update the remote branch directly.

git push origin local_branch:remote_branch

So my workflow would look more like

git push origin master:release

Happy Automation!

Introducing CommandAllThings

I'd like to introduce a simple little tool/(set of scripts) I threw together last weekend called CommandAllThings.

Some background

Do you use any command line build tools like GulpJS, GruntJS, Rake, etc?

I leverage these tools in many projects, both at work and on my own projects. I recently noticed that the muscle memory I've developed was slowing me down as I switch between projects and inadvertently use the wrong tool in the wrong project.

When working on one project all day and typing rake test throughout the day, then switching to another project not using rake I found myself still typing rake test even though I needed to type gulp test, or grunt build. This really messes with my flow. All I wanted to do was test or build the current project.

So I created CommandAllThings.

What is it?

In short, it's a very simple abstraction on top of your usual task runners like GulpJS, GruntJS, rake, etc that allows you to accidentally type the wrong tool and still accomplish the desired task with the right tool.

By using aliases in either PowerShell or Bash we can route, rake, gulp, grunt, etc to CommandAllThings which will inspect the current directory, determine the correct tool and execute your task(s) with the correct tool.

This is great. Now when I type in the wrong command rake test in a gulp project, I don't get slapped in the face with an error saying "cannot find a rakefile." Instead I continue on my way like I knew what I was doing.

example screenshot of commandAllThings

Does it only work on Windows or on the Mac?

At the moment it works on both.

  • For Windows I have an implementation in Powershell.
  • For the Mac you can alias to a Bash script.

Download at GitHub!

Check it out!

What's next?

I'd like to look at adding other tools to the list. You can check out the project for other task runners I know about. And if you have any thoughts on how to detect the other types, drop me a note in the issues (or consider sending over a pull request).

I'd also love to get some feedback on how to best or more easily get this into peoples's development environment. For now it's pretty manual and since it's all about your profile, a bit personal, so probably a good thing that it's not automatically installed.

Happy Commanding!

How to compile plain *.js (JavaScript) files with the TypeScript Compiler

Challenge

Let's say you've been tasked with researching what porting your existing JavaScript solution to TypeScript may look like or maybe you're curious what this process would be like before you propose it to a lead or project manager.

The first hurdle you may stumble upon is – the tsc (TypeScript compiler) requires all of your files end with a .ts file extension. This can make quickly prototyping a port challenging. To get an idea of what a port to TypeScript will look like you don't want to deal with first renaming all of your files to .ts. Especially since there are probably files you want to not rename to TypeScript (like jQuery or AngularJS etc.

And since:

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.

it seems reasonable that you could acquire the benefits of the TypeScript compiler for even your existing JavaScript codebase.

Challenge Accepted.

The TypeScript compiler is open source, so let's take a dive into the compiler to see if this is something we can work around…

What are the steps we need to accomplish to make the compiler accept plain .js files?

  1. Get It
  2. Copy it
  3. Hack it
  4. Use it

Get it

Before we can get too far, let's first install the compiler onto our system.

I'll use npm to install typescript

npm install -g typescript

Note the -g here tells npm to install typescript globally. This adds the TypeScript compiler to your PATH so you can get right at tsc'ing your TypeScript code.

Copy it

We probably don't want to modify the globally installed version of tsc so we'll create a copy on our system to play around with. But, before we can do that we need to find where it is.

If on Windows or Mac

where tsc

NOTE: if you're using the PowerShell console on windows be sure to type out where.exe tsc because where is aliased to Where-Object in PowerShell which won't help us out in this case.

Once you've found the path to your version of tsc

Mine was in

  • C:\Users\jason\AppData\Roaming\npm\tsc
  • C:\Users\jason\AppData\Roaming\npm\tsc.cmd

Look at the contents of the tsc.cmd for Windows and tsc for non Windows machines. You'll notice that they are essentially executing node.exe passing in an argument to another tsc file in the node_modules path.

Take the two tsc and tsc.cmd files, copy them into a working folder MyJSCompiler and rename them. I named mine jsc and he shall be my squishy. Then take the contents of the node_modules/typescript/* folder (and path structure) and copy them to your working directory.

When you're done you should have a directory that looks something like this


??--MyJSCompiler
  |   jsc                 <-- notice the re-named file from tsc -> jsc
  |   jsc.cmd             <-- notice the re-named file from tsc.cmd -> jsc.cmd
  |   
  ----node_modules
      ----.bin
      |       tsc
      |       tsc.cmd
      |       
      ----typescript
          |   .npmignore
          |   CopyrightNotice.txt
          |   LICENSE.txt
          |   package.json
          |   README.txt
          |   ThirdPartyNoticeText.txt
          |   
          ----bin
              |   lib.d.ts
              |   tsc
              |   tsc.js
              |   typescript.js
              |   
              ----resources
                  |   diagnosticMessages.generated.json
                  |   
                  ----(*.json files excluded for brevity)

Now you should be able to call your local version of jsc at the command line.

Hack it

Since we have a local version we can hack on now, let's find out what needs to change. Thanks to Ryan for already giving us a clue here.

Open up the node_modules/typescript/bin/tsc.js file (in our working directory from the previous step) and apply the below diff/changes.

     function isTSFile(fname) {
-        return isFileOfExtension(fname, ".ts");
+        return isFileOfExtension(fname, ".ts") || isFileOfExtension(fname, ".js");
     }

We've now implemented a small tweak to the TypeScript compiler that allows us to compile plain JavaScript files.

Use it

I won't be going into how to use the tsc compiler in this post, but you can now call the compiler passing along your *.js files and begin learning what changes you will need to make to your existing codebase to satisfy the compiler.

Be sure to use the --out FILE or --outDir DIRECTORY options because if you don't the compiler will take the input javascript file and overwrite it with it's compiled version.

!!WARNING!! I'll say that again, to use it, be sure to use the --out FILE or --outDir DIRECTORY options because if you don't the compiler will take the input javascript file and overwrite the original with it's compiled version.

With source control, this can potentially be a fun experiment to see what TypeScript's version looks compared to your own, but I'll leave that up to you to play with.

Best of luck on your port to TypeScript.