Useful Git Aliases

Here are some useful aliases for Git:

git ls

git log is pretty useless. It doesn't list the branch the commit was made on, it doesn't show colors and it doesn't show branching visuals. But with this alias you get all that. List commits in short form, with colors and branch/tag annotations and visuals.

git config --global alias.ls "log --color --graph --pretty=format:
  '%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)
  %Creset' --abbrev-commit --decorate"

git ll

List commits as above but also showing changed files.

git config --global alias.ll "log --color --graph --pretty=format:
  '%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)
  %Creset' --abbrev-commit --decorate --numstat"

git lds

List one line commits that display dates.

git config --global alias.lds "log --color --graph --pretty=format:
  '%Cred%h% %ad%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)
  %Creset' --abbrev-commit --decorate --date=short"

git grep

Find a file path in codebase which contains a string or pattern.

git config --global alias.grep '!git ls-files | grep -i'

git ltg

Show the last tag.

git config --global alias.ltg 'describe --tags --abbrev=0'

git unpushed

Sometimes I wonder what is left to push to origin. Git doesn't have an easy way to see this, but with this alias you get the commits that haven't been pushed to upstream. Also you get colors and branching visuals like above.

git config --global alias.unpushed "log --branches --not --remotes
  --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset
  %s %Cgreen(%cr) %C(bold blue)%Creset' --abbrev-commit"

git undo

Git doesn't have an undo option to undo the last commit. But with this alias you can easily undo the last commit.

git config --global alias.undo 'reset --hard HEAD~1'

However if you've added many files in the last commit (like a package or something), git doesn't delete them. But you can do that with this alias: git clean -f -d

git visual

Run a git graphical user interface on top of your git directory.

git config --global alias.visual '!gitk'

git la

Going meta! List out all your aliases.

git config --global alias.la '!git config -l | grep alias | cut -c 7-'

Basic stuff

Of course I use a ton of basic shortcuts, here’s a few ingrained in my fingertips:

cp = cherry-pick
st = status -s
cl = clone
ci = commit
co = checkout
br = branch
diff = diff --word-diff
dc = diff --cached

Enjoy!

Three Rules for Project Selection

Today I ran across a thought provoking article on Dr. Dobb's. The thesis is that there is a perception that Open Source projects copies what already exists and it's in Closed Source where the real innovation occurs. This perception exists in part because how geeks choose what to work on.

There is most definitely evidence to the contrary and also to support that perception, but the main point of the article is that there is a fundamental problem in Open Source which manifests itself as this perception. The problem is with project selection.

Now, Dijkstra wrote a memo in 1982 that describes 3 steps to use when selecting a topic for your research. These rules translate really well to hacking and all geeks should consider them when selecting an Open Source project to work on. The rules are:

  1. Raise your quality standards as high as you can live with, avoid wasting your time on routine problems, and always try to work as closely as possible at the boundary of your abilities. Do this, because it is the only way of discovering how that boundary should be moved forward.
  2. We all like our work to be socially relevant and scientifically sound. If we can find a topic satisfying both desires, we are lucky; if the two targets are in conflict with each other, let the requirement of scientific soundness prevail.
  3. Never tackle a problem of which you can be pretty sure that (now or in the near future) it will be tackled by others who are, in relation to that problem, at least as competent and well-equipped as you.

Let's break this down a little so it can be easily digested.

Rule 1 is an internal one and it tells us that the obviously possible should be shunned as well as the obviously impossible: the first would not be instructive, the second would be hopeless, and both in their own way are barren.

Next, Dijkstra was referring to scientific projects, but Rule 2 can be easily mapped to software projects also.

Rule 3 is the most important from an Open Source perspective. It ensures that your contributions are unique and move the-state-of-the-art forward. As Dijkstra so eloquently puts "If others will come up with as good a solution as you could obtain, the world doesn't loose a thing if you leave the problem alone. A corollary of the third rule is that one should never compete with one's colleagues. If you are pretty sure that in a certain area you will do a better job than anyone else, please do it in complete devotion, but when in doubt, abstain."

I will be applying this rules to my future project selection. I hope you do too.

What is the best reply if your boss asks "How are you doing?" at the urinal?

This is totally off-topic for this site but I really had to take not of this really interesting question that I saw asked on Quora:

This is something which has happened so many times with me now. Have you had similar incidence? What was your reply when your boss asked that question? Or what would you reply if in future you face such a question?

The following answer provided could not be more eloquent:

Take advantage of the opportunity to get valuable face time with your boss. I'd recommend something like:

"I was under a lot of pressure, but things seem to be flowing well now. I've got a firm grip on the situation and am seeing some good output. It may take awhile before I achieve completion, but it's important to take one's time in order to stay on target. I expect to wash my hands of the whole thing in the next several minutes."

Check if a bit is set and bit-masking in CSharp

Today I was talking to a co-worker and the conversation went into the subject of bit masking. So I wrote the quick command line tool below to explain how bit masking works and how to find out if a bit is set or not on a value.

using System;

namespace bittest {
    class Program {
        public static void Main(string[] args) {
            while (true) {
                WL(""); W("Enter a number [0-255]: ");

                int i = Int32.Parse(RL());
                string sbin = Dec2Bin(i);
                byte b = (byte)i;

                WL(""); WL(SF("{0} in binary is {1}. It has {2} bit(s)",
                              new object[] {i, sbin, sbin.Length}));
                WL(""); W("What bit do you want to check: ");

                int pos = Int32.Parse(RL());

                WL(""); WL(SF("Bit {0} is {1}set!",
                              new object[] {pos, IsBitSet(b, pos) ? "" : "not "}));
                WL(""); W("Continue [Y/n]: ");

                if (RL() == "n")
                    break;
            }
        }

        static Func<int, string> Dec2Bin =
            value => Convert.ToString(value, 2);
        static Func<byte, int, bool> IsBitSet =
            (b, pos) => (b & (1 << pos)) != 0;

        static Action<object> W = o => Console.Write(o);
        static Action<object> WL = o => Console.WriteLine(o);
        static Func<string> RL = () => Console.ReadLine();
        static Func<string, object[], string> SF =
            (frmt, obj) => String.Format(frmt, obj);
    }
}

Enjoy!

Running a Linksys WRT54GL with DD-WRT behind an AT&T UVerse 2Wire Gateway

For many years I have been an ADSL subscriber receiving 3 Mbps service from AT&T. The line came into the house and into a simple ADSL modem that connected to a Linksys WRT54GL running DD-WRT firmware, which was setup to serve as the Internet gateway for all computers in the house. I won't go into the virtues of this particular model of Linksys router running this particular firmware, but suffice it to say that those who know what I'm talking about will need no further explanation.

Linksys WRT54GL

Recently, we moved to a new house and AT&T would not let me transfer the ADSL line to the new address, but they said they would be happy to set me up with this shinny new digital service they call UVerse. After doing some checking, I noticed that the reviews from customers were mixed, but that the speeds provided were pretty decent. I was leaning towards cable service, but the wife likes AT&T, so we signed up for the 12 Mbps UVerse Internet plan. The AT&T technician came to the house and set it all up in the phone box outside — inside the house he hooked the line up to a 2Wire 3600HGV device. When he saw my Linksys router laying nearby, he said "With this beauty right here..." and he showed me the 2Wire device, "... you won't need that Linksys router of yours." That should have been my fist sign that something was amiss.

2Wire 3600HGV

The one redeeming quality of the 2Wire device is that it does have a really strong radio signal, but other than that the firmware running on it is really crippled and perhaps can do a little more than 10% of what the DD-WRT firmware is capable of. The conspiracy theorist in me says that the 2Wire hardware and software are probably more capable than AT&T is willing to document and let the users have access to,

Anyway, the ideal situation for me was to turn the 2Wire into a dumb modem and use my Linksys as the gateway, just like the old ADSL days... but that was easier in concept than in practice. There are all kinds of gotchas and tricks to get it setup, like the Router Behind Router detection. After much trial and error, I persevered, and below is the result of my research into how to get this setup to work.

At this point I recommend that you make a backup of your current DD-WRT setup by going to Administration and then the Backup menu and then clicking the Backup button.

The first step is to get the Linksys router ready for the setup. Make sure you can reach it and connect to it with a browser by going to http://192.168.1.1/. I used an Ethernet cable directly from my laptop and into one of the 4 LAN ports on the Linksys. Once you logged in to the Linksys, go to Setup and then Basic Setup. Under WAN Setup, make sure that the Connection Type is DHCP and give the device a unique Router and Host name. Under the Network Setup area, change the Local IP Address to something like 10.0.0.1 — just make sure that the IP you choose is in a different subnet than 192.168.1.X. With this setup we are trying to avoid conflicts between the Linksys DHCP and the 2Wire DHCP servers and in general we want the 2 devices in separate networks anyway.

DD-WRT WAN Setup

The next step is to connect to the 2Wire device. I unplugged the Ethernet cable from the Linksys and connected it to one of the LAN ports on the 2Wire. Now you should be able to reach the 2Wire setup interface by pointing your browser to http://192.168.1.254/. If at first you are unable to connect, then check your current IP address. Since the Linksys was changed to a different network, you may have gotten an IP in the range 10.0.0.X. You can fix this by releasing and renewing your IP lease. Also, in order to apply any changes to the 2Wire device you will need to know the System Password which should printed on a label on the device.

2Wire 3600HGV Unit Back

Before moving on, I want you to consider the above image for a moment. Here's what's going on:

  1. The blue ethernet cable connects the the 2Wire device to the WAN Port on the Linksys.
  2. The yellow ethernet cable was used to connect the laptop directly to the 2Wire device and also to the Linksys previously.
  3. The green RJ11 cable is the digital data cable connecting to the Internet at large.
  4. The white RJ11 cable is for the phone/voice service and goes into the telephone set.

Linksys WRT54GL Back

As you can see in the above image, the blue cable connected to the 2Wire device terminates into the WAN port of the Linksys device.

Now, back from this little tangent, I was about to connect to the 2Wire device with the browser. Once connected, go to Settings and the LAN tab and click on the Wireless link and ensure that the value under Wireless Interface is set to Disabled. I want the Linksys in charge of providing Wireless and DHCP services. Once that's done, click the Save button at the bottom of the page.

2Wire Disable Wireless

Next I need some way for the Linksys to receive all inbound Internet traffic into the house. This can be done by putting the Linksys in DMZPlus mode in the Firewall setting of the 2Wire device. Go to the Settings tab in the 2Wire setup interface and then click on the Firewall tab and click on the Applications, Pinholes and DMZ. Choose the DD-WRT (or whatever name you gave your device) from the list under Select a computer. Then further down on that same settings page under Edit firewall settings for this computer select the choice Allow all applications (DMZplus mode). Make sure to click the Save button at the bottom of this page when all done.

Put DD-WRT in DMZPlus Mode

You can verify that the 2Wire setup is correct by going to the Status page under the Settings and Firewall sections and seeing that the DD-WRT device is listed under the Current Applications, Pinholes and DMZ Settings: Custom and that it was assigned a public Internet IP.

One more side bar is called for at this point in the setup process. If at any point in time during the setup you are faced with a warning from the 2Wire device that it has detected a Router-Behind-Router setup, please just ignore it as the final outcome of the setup I am doing will render that type of detection irrelevant. As a matter of fact, while on the 2Wire setup interface, just go to the Settings tab and then the System Info tab and the Event Notifications link and make sure that the option Enable detection of router-behind-router conditions is not checked. Save your change before moving on.

Let's do a quick recap: We first put the Linksys device in DHCP mode at the WAN level and gave it a recognizable name, then we gave it a different subnet IP than the default 2Wire IP. Next we disable the Wireless service on the 2Wire device and then we put the Linksys device in DMZPlus mode in the 2Wire configuration screens. We also verified that the Linksys is getting a public IP from the 2Wire perspective.

Ensure DD-WRT has Public IP

Next we need to ensure that the Linksys is getting the public IP address from it's own perspective (see above image). Go to the Status tab and then the WAN tab on the DD-WRT setup interface. Under the WAN section on that page ensure that the IP Address value is the same as the one assigned to the DD-WRT in the 2Wire interface. I obfuscated the public values here for obvious reasons. This is where I was a little stumped when I went through these steps for the first time. If at first your Linksys/DD-WRT doesn't recognize the public IP, try using the DHCP Release button or rebooting the Linksys. I had to reboot the Linksys twice initially, but it has been working for me without any issues for a week now.

I hope this write up is useful to you...

Virtual Box Fails to Start Virtual Machine

I recently moved to a new house and during the move something really peculiar occured with my computer: It seems that the UEFI chip reset to the factory defaults. The 2 visible outcomes of this was that the computer clock was reset back to 2009-01-01 00:00:00 and that the Hardware Virtualization on the CPU was turned off. The latter manifested itself as an error when I tried to run virtual machines with Virtual Box. This was the error generated by Virtual Box:

VBox Error

To fix these errors I had to first set the correct system date and timezone offset and then I had to boot into the UEFI setup utility and enable hardware virtualization for the Intel i7 CPU. This setting is going to be slightly different on every motherboard, but after I enabled it VBox started to run the VMs as usual.

Install the Real Firefox on Debian 7

If you have ever played around with the Debian distribution proper, you will quickly notice that Firefox is not available as a browser and in its place is something called IceWeasel. Here I will show you how to install the real Firefox browser on Debian 7.

The first step is to remove the IceWeasel package if it's installed:

$ sudo apt-get remove iceweasel

Next, we will make use of a Linux Mint package repository that targets Debian proper. To do this add the following line to you /etc/apt/sources.list file:

deb http://packages.linuxmint.com debian import

Now when you update your package list you will see an error like so:

$ sudo apt-get update
... a ton of output ...
W: GPG error: http://packages.linuxmint.com debian Release: The following
signatures couldn't be verified because the public key is not available:
NO_PUBKEY 3EE67F3D0FF405B2

This happens because you don't have the proper key for the Linux Mint repository. To get a valid PGP key do the following:

$ sudo gpg --keyserver pgp.mit.edu --recv-keys 3EE67F3D0FF405B2
$ sudo gpg --export 3EE67F3D0FF405B2 > 3EE67F3D0FF405B2.gpg
$ sudo apt-key add ./3EE67F3D0FF405B2.gpg
$ sudo rm ./3EE67F3D0FF405B2.gpg

Now you should be able to update the package list successfully. Then what's left to do is to install firefox and you can do that like so:

$ sudo apt-get install firefox firefox-l10n-en-us

Enjoy firefox!

Some Notes on Using Git with Cygwin on Windows

Just recently I rebuilt a system that I use for work. After I installed Cygwin on it, I started getting some weird errors when using git with ssh to do some source control tasks.

When doing a fetch, pull or push to/from origin, or really any git command that uses ssh to communicate, the ssh client would complain with the error:

Could not create directory '/home/jgg/.ssh'.
The authenticity of host 'github.com (204.232.175.90)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)?

Once I enter yes, I get the following:

Failed to add the host to the list of known hosts (/home/ME/.ssh/known_hosts).

This was happening everytime I was using git under cygwin and very quickly the situation became completely unsustainable. But after doing a little research, I found a solution that is pretty simple:

  1. Locate the passwd file, which is usually at C:\cygwin\etc\
  2. Open it with your prefered editor
  3. On the line that starts with your username, change the section that reads /home/ME to read /cygdrive/c/path/to/home/folder/ME or wherever your home folder is.
  4. Save the changes and restart the Cygwin Terminal

Expect to see the authenticity check one final time and see the ssh client actually be able to write to the known_hosts file.

Build Emacs from Source in Ubuntu 13.04

Over the years I have written several of these articles and I find that every 2 to 3 years I need to re-write these notes because the installation process diverges enough from the previous set of steps that it warrants a re-write.

The main Linux distribution that I have settled on lately is Xubuntu, which is a XFCE-based version of Ubuntu. I dabble in other distros also and I am experimenting a lot lately with Arch and other Debian-based distros. One thing is clear, the versions of GNU Emacs available with each distribution are different. So, as a standard I will always try to download the latest stable GNU Emacs sources and build it on the system I am using at the moment. This ensures that I have a homogeneous set of features across the different machines and also that I am pretty close to the bleeding edge.

In order to get to this state with your Emacs install you can follow the below steps. These steps are focused on a Debian-based distro using APT. I will assume that you have a base Debian or Ubuntu system already installed with a common GUI environment. Again, I wrote these notes for a Xubuntu system running XFCE. Let's start by downloading and installing the tools needed to build Emacs:

$ sudo apt-get install build-essential git git-core curl
$ sudo apt-get install automake autogen autoconf ssh

Next, you need to get the sources for Emacs. There is two ways to go about doing this: 1) Clone the sources from an Emacs repository directly or 2) Download the latest compressed source tarball from a FSF/GNU mirror site.

To clone the Emacs source from a repo, do the following:

$ cd ~/Downloads
$ git clone git://git.savannah.gnu.org/emacs.git

Cloning will take several minutes, because git will get all the history and changes and we all know that Emacs has a long history. The clone method is the way to go for those who will hack on emacs itself. The easier way to do this, however, and the way that I prefer is to pull the source tarball from a mirror. A list of available mirrors can be found at the FSF site. You can pick any of these sites and download from it. The command to do that will differ based on the mirror you pick, but should look something like this:

$ curl -O http://mirror.sdunix.com/gnu/emacs/emacs-24.3.tar.gz

While you are downloading the tarball or cloning the repo you should open another terminal window and start installing some needed Emacs dependencies in parallel:

$ sudo apt-get install texinfo libncurses5-dev libgtk2.0-dev libgif-dev
$ sudo apt-get install libjpeg-dev libpng-dev libxpm-dev libtiff4-dev
$ sudo apt-get install libxml2-dev librsvg2-dev libotf-dev libm17n-dev
$ sudo apt-get install libgpm-dev libgnutls-dev libgconf2-dev libdbus-1-dev

Once the above deps are installed and you finished retrieving the sources for Emacs, it's time to do the actual build. Decompress the source if you downloaded it and change directory into the Emacs source:

$ tar -zxvf emacs-24.3.tar.gz
$ cd ~/Downloads/emacs-24.3/

Configure the build according to what you want your installation to look like:

$ sudo ./autogen.sh
$ ./configure

I use the vanilla configuration, but you can change it to what suits you best and you can view all alternatives by using ./configure --help ... If you don't like what configure has done for you (read the configure output) you can also clean things up and start over with make distclean.

The key thing that I am trying to achieve is a message from configure that looks very similar to the below output. Note all the yes values next to all the stuff that configure checks for; this is a direct outcome of installing all the dependency packages above. Emacs absolutely needs texinfo, ncurses, an X toolkit and the image libraries to even build. The rest of the stuff is nice to have, but if you don't install it you will get a no from configure for that feature check.

... a ton of output

Configured for `x86_64-unknown-linux-gnu'.

  Where should the build process find the source code?    ~/Downloads/emacs-24.3
  What compiler should emacs be built with?               gcc -std=gnu99 -g3 -O2
  Should Emacs use the GNU version of malloc?             yes
      (Using Doug Lea's new malloc from the GNU C Library.)
  Should Emacs use a relocating allocator for buffers?    no
  Should Emacs use mmap(2) for buffer allocation?         no
  What window system should Emacs use?                    x11
  What toolkit should Emacs use?                          GTK2
  Where do we find X Windows header files?                Standard dirs
  Where do we find X Windows libraries?                   Standard dirs
  Does Emacs use -lXaw3d?                                 no
  Does Emacs use -lXpm?                                   yes
  Does Emacs use -ljpeg?                                  yes
  Does Emacs use -ltiff?                                  yes
  Does Emacs use a gif library?                           yes -lgif
  Does Emacs use -lpng?                                   yes
  Does Emacs use -lrsvg-2?                                yes
  Does Emacs use imagemagick?                             no
  Does Emacs use -lgpm?                                   yes
  Does Emacs use -ldbus?                                  yes
  Does Emacs use -lgconf?                                 yes
  Does Emacs use GSettings?                               yes
  Does Emacs use -lselinux?                               no
  Does Emacs use -lgnutls?                                yes
  Does Emacs use -lxml2?                                  yes
  Does Emacs use -lfreetype?                              yes
  Does Emacs use -lm17n-flt?                              yes
  Does Emacs use -lotf?                                   yes
  Does Emacs use -lxft?                                   yes
  Does Emacs use toolkit scroll bars?                     yes

... more output

Now you can go into the actual build of Emacs by issuing the following command:

$ make

And then last step is to install the Emacs you just finished building:

$ sudo make install

... and run it:

$ emacs &

Enjoy hacking with Emacs!

P. S. One last step that is personal and relevant to me only is to install my Emacs configuration. Execute the following to accomplish that:

$ rm -r .emacs.d
$ git clone git@github.com:gorauskas/.emacs.d.git

You will of course need to have the correct encryption key in order to clone the repo like the line above.

Grepping Multiple Files Recursively

Recently I was faced with the task of looking for the occurences of a variable name in all files in a directory recursively. Here is a quick bash incantation that accomplishes that:

$ find . -type f -print0 | xargs -0 grep -l variable-name

The above can be understood better if we break it down at the pipe character. To the left of the pipe we use the find command to generate a list of file names recursively starting at the current directory. We use find with the -print0 action because we are passing the output to another program via a pipe and this way the list of file names come out delimited by a null character. Next, we feed the output of find to the input of xargs which will split the long list of file names into sublists and calls grep once for every sublist. The grep command then filters the list of file names and returns only the ones that contain the variable-name string in them.

Pretty cool, eh?