3 Golden Nuggets: Git

Welcome to the second installment of the ‘3 Golden Nuggets’ series. If you’ve yet to read a previous post in this series, it entails three key features within a predetermined subject. This time we are looking at a big player in the SCM (source code management) world, Git. I’ve spent 80% of my development life maintaining, preserving and sharing my codebase through this truly impressive piece of software; from restoring old code to setting up feature branches, Git has been my cyber superhero through it all. Here are a few tips which I think are deemed worthy of mentioning:

Change protocol access to prevent firewall blocking

There has been times where I’ve been up all night trying to solve a bug and every attempt has proved unsuccessful. I then proceed to wake up the next day, still troubled by this problem, eat my breakfast and go to work. Before I know it midday strikes and my only focus for the next 30 mins is to have another crack at this bug; hopeful that a fresh mind will provide a more fruitful conclusion. My attempt is quickly cut short by git clone providing me with an ‘unable to connect a socket (Connection timed out)’ error; further investigation reveals that the corporate firewall at work is preventing me from accessing the git: protocol (9418).

This is usually standard practise for corporate firewalls to block unconventional ports in order to improve security of their intranet. The obvious solution would be to start utilising the HTTP protocol which Git provides. You can achieve this by modifying the git config to perform some basic URL rewriting and force all Git commands to use the HTTP instead of the GIT protocol. Simply issue the following command in your terminal window:

You can then confirm your changes by running:

You’ll see the following line in the output:

If you would like to use a more specific URL in the replacement, you can issue something like this:

In the event of a URL matching multiple replacements, the longest match wins.

Reconcile a detached HEAD

In order for us to understand the problem, we first need to acquire a firm grasp of what a HEAD is and what it means when it is detached.

HEAD is a symbolic name of the currently checked out commit. When a HEAD is not detached it points to a branch’s “ref” and the branch points to the commit, which in turn means the HEAD is “attached” to a branch. When you perform a new commit, the branch that HEAD points to is updated to point to a new commit, and the HEAD follows since it just points to the branch. So to summarise we have HEAD => branch “ref” => Commit which translates to HEAD => refs/heads/master => 23a02924078923f8b62811326d108de991d1a95a. Please note the commit can also be referred to as the current tip or “head” of the master branch.

When HEAD is detached, it points directly to a commit – instead of indirectly pointing to one through a branch. So, in other words a detached HEAD is on an unnamed branch. You can continue to work on a detached HEAD, however you run the risk of losing history along the way.

Your first point of call would be to issue the git rebase command. If you finish the full rebase operation, it will update your original branch with the cumulative result of the rebase operation and reattach HEAD to the original branch. However if the rebase process never fully completed, it will leave you with a detached HEAD pointing to the commit that was most recently processed by the rebase operation.

In our example below the HEAD has detached from your master branch and we are looking to restore the HEAD => master => commit link. To recover a detached HEAD after a failed rebase, you should start by creating a branch that points to the commit currently pointed to by your detached HEAD:

This will reattach your HEAD to the new temporary branch. Next you want to update your master branch to point to the new temporary branch:

The temporary branch has now become redundant as the master branch is now pointing to the same commit so we can remove it:

The final step is to push the reestablished history:

It is likely you will need to use -f (force) to push if the remote branch can not be “fast-forwarded” to the new commit, i.e. rewrote some of the history.

Stashing your work

You’re happily hammering at the keyboard building an awesome new feature for your application and then BOOM, a live bug is flagged. If you’re awesome enough to be a Git user then you needn’t panic. Just whip out your new best friend, git stash.

Think of the stash command as your own personal clipboard in Git – you can stash any working changes in your current branch and return to a clean working directory, so you can start work on something else. You can do everything you would normally do in Git without losing your clipboard; once you’re happy to continue working on those changes, you can simply issue git stash pop on the stash’ original branch to bring back all your changes.

Furthermore you can store a number of stash’ in your ‘clipboard’ and easily issue git stash list to view all the current stash’ – detailing the stash name, branch name and a short description. Utilising the previous stash pop command, you can specify the stash you wish to bring back, e.g. git stash pop stash@{3}. You can find a full list of features over at the Git Documentation.

I hope these have proved useful for you and your development codebase.

05th December 2013