Posts filed under 'IT'


cp /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
echo "America/Los_Angeles" > /etc/timezone
# ... because there is no /usr/share/zoneinfo/America/San_Francisco
/etc/init.d/ntp-client restart


2 comments February 3rd, 2012

Yet another GIT branching guide

If you always work on the master branch, git pull and git push commands are just what you need. If instead you need to work on a branch, something more need to be said. First, some explanations.

  • GIT uses branches just like SVN: a branch is a different path of developement
  • There is no implicit “primary” branch (SVN has instead the “trunk”); that said, the main branch is often called master (GIT will give this name to the main branch when creating an empty repository).
  • Branches can be either local or remote:
    • A local branch is a branch that exist on the local repository only; you can see a list of local branches using git branch.
    • A remote branch is instead a branch that exists on a remote repository, therefore visible to anyone that has access to it. Use git branch -r to see all the remote branches known to you. Remote branches have generally a name in the form origin/$branchname, because origin is the default alias that is given locally to the remote repository.

Now, before creating a branch, you may want to ask yourself some questions:

  • Do I want to propose some changes to the world, or instead do I just want to try out some things?
  • Do I need to follow another guy’s branch, or am I working alone on the subproject?

If you need to work in team, you need to create a branch on the remote repository (if someone else did not already) and then setup a local branch to “link” to it (GIT calls this tracking); otherwise, you just need a local branch.

Let’s start from the easy part: how to create a local branch.

Local branches

Suppose that I am following the master branch, but I want to try the foorazor approach to the problem. I create a “topic” branch just for that:

git branch foorazor
git checkout foorazor
# or, in a single command:
git checkout -b foorazor

Now I start working on it, making commits and whatever. If, some time later, I see that the foorazor approach is wrong, I just delete that branch:

git checkout master   # to switch to that branch
git branch -d foorazor    # delete the wrong branch
# If the branch content was not merged (and this is perfectly fine sometimes), GIT complains with:
# error: The branch 'foorazor' is not fully merged.
# If you are sure you want to delete it, run 'git branch -D foorazor'.
git branch -D foorazor   # so, just force its deletion

If, instead, the foorazor approach turns out to be useful, I merge it back in the master branch:

git checkout master
git merge foorazor   # you may need to manually merge some things here, if there are conflicts
# edit the files with conflicts, git-add them when ready and git-commit to resolve the merge
git branch -d foorazor   # delete the now unneeded branch, if no development is needed anymore on that topic

Note that no git push was ever made: we never informed the central repository of our local branch. If, of course, I have completed the work on foorazor and I have merged it, now the code exists also on the master branch, so the next git push will transfer those commits to the central repository.

Working with a remote branch

Let’s take branches to the next level. Someone asked me to work on his awesome branch to fix some bugs. I have already fetched the whole repository with git clone, so the remote branch is already known to me:

$ git branch -r

Since I know that there is nothing awesome in fixing bugs committed by other people, I decide to track the awesome remote branch with a descriptive local name: (there is no need to have different remote and local names, I do it to point out the namespace differences)

git checkout --track -b boring_work origin/awesome

Now I work on the local branch boring_work as always. I fetch my friend’s changes with git pull and do commits locally; when I want to give him back my changes, I type:

git push origin boring_work:awesome

This command pushes the changes from the local boring_work on the remote branch awesome on the repository origin: note that you can use just git push origin awesome if you used the same name locally (and probably you should do so if you are not an advanced user).

NOTE FOR ADVANCED USERS: by default, if no remote branch name is given on the command line (remember that the syntax is git push ${reponame} ${local}:${remote}), GIT pushes to a remote branch with the same name of the local one. So, even if boring_work tracks origin/awesome, git push origin boring_work will create another branch called boring_work on the remote repo. This happens because the configuration option push.default has a default value of matching (see man git-config). Solutions?

  • Either use a local name that is the same of the remote one (git checkout --track -b awesome origin/awesome);
  • or, if you want more freedom, configure the local repo with git config push.default upstream, that says GIT to push the current branch to its upstream branch, not the one with the same name.


When I’m done helping my friend, I just type

git checkout master
git branch -d boring_work

and forget about the past.

How to create and delete a remote branch

What if I want to create a brand new branch on the remote repository?

This command creates a branch called new_branch, as a copy of the remote’s master (actually, as a copy of the remote’s HEAD, but, if nobody messes up the remote repo by actively running commands inside it, the result is the same):

git push origin origin:refs/heads/new_branch

Now you can fetch it locally as explained above.

If instead you want to duplicate a remote branch, use:

git push origin origin/old_branch:refs/heads/new_branch

Note that none of the previous command sets up a local branch.

To delete a remote branch, just use:

git push origin :remote_branch

that can be remembered easily as “using remote repo origin, push “empty” to remote_branch“. The deletion command does not need the “refs/heads” prefix because the branch name is already known remotely and therefore can be looked for in the standard places.

1 comment September 9th, 2011

SVN to GIT repository migration

Last week we at NetGroup decided that it was time to move our SVN repositories to GIT. While I always use svn-git to interface with Subversion, a server-side move was long awaited.

Here follows a step-to-step migration history, loosely based on this article, that I found as the most useful resource on the Web among those suggested by Google. I publish the code here to help you migrate as well 😉


First of all, I listed all the active SVN authors in the repository. From an updated SVN working copy, I created an authors.4git file:

svn log --xml | grep author | sort -u | sed 's:.*>\(.*\)<.*:\1 = :' > authors.4git

I filled the output file with actual username information, using the following syntax:

username = Name Surname <>
username2 = Name2 Surname2 <>
(no author) = no author <(no author)>

The last line is important for those commits that lacked an author (from a even older CVS2SVN migration).

Fetch and convert branches and tags

I started to fetch the SVN repo using git-svn:

git svn clone ssh://path/to/old/repo/ --authors-file=authors.4git -s svn2git_tmpdir
cd svn2git_tmpdir

Some sources suggest to use --no-metadata when cloning, but I wanted to preserve SVN commit information in the GIT log: you’ll see later why.

Then I converted SVN tags to actual GIT tags:

for t in `git branch -r | grep 'tags/' | sed s_tags/__` ; do
	git tag $t tags/$t^
	git branch -d -r tags/$t

I removed most of the leftovers from git-svn:

git branch -d -r trunk
git config --remove-section svn-remote.svn
rm -rf .git/svn .git/{logs/,}refs/remotes/svn/

In the end, I converted the SVN branches, that git-svn created as remote GIT branches, into actual GIT local branches:

git config remote.origin.url .
git config --add remote.origin.fetch +refs/remotes/*:refs/heads/*
git fetch

Additional tweaks: history and commit messages rewriting

Since the migration is a one-time effort, before completion I wanted to fix some longstanding issues in our repo.

The first one was the removal of some useless commits: a couple of times someone managed to commit loads of useless files, forcing someone else to revert that commit. So, I found the SHA identifier of the oldest of those commits and launched (note the tilde sign at the end):

git rebase -i ${OLDESTBADCOMMIT}~

GIT fired up my $EDITOR and I removed all the useless commits (both the adding and the reverting ones), by deleting the appropriate lines in the configuration file.
The history rewriting was successful. I had to type a couple of times:

git reset
git rebase --continue

because some commits became empty ones and I wanted to discard them. The git rebase had to be run on all the branches that included those useless commits (hint: use git branch --contains ${BADCOMMIT}).

The second problem was the preservation of the SVN metadata inside the GIT commit logs. This was needed because some SVN commit messages referenced other SVN revision numbers, so I wanted to keep those references intact. On the other hand, the previous git rebase had mangled the GIT-committer property of the rewritten commits, by setting me as the committer, even if the author property was left intact (you can see the difference on an actual GIT repository using git log --format=fuller). Both issues can be solved with one command:

git filter-branch -d /tmp/tmpfs/gitrewrite \
	--msg-filter 'sed "/git-svn-id:/s;^.*/\([^/]*\)@\([0-9]*\).*$;Autoconverted from SVN (revision:\2, branch:\1);"' \
	-- --all

The -d switch ran the operation (that is said to be I/O intensive) on a tmpfs mount. You can skip it if the history is short enough, or if you don’t care about it.
The first filter edited the git-svn-id lines into a prettier format; the second one restored the GIT-committer properties that I had lost previously.
In the end, --all runs those filters on all the branches.

Push to the new repo

Before pushing to the new repo, I let GIT collect the garbage by pruning unreferenced objects:

git gc --aggressive --prune=now

And, finally, I completed the migration by pushing everything on a bare, empty repository that I had already set up:

git push --all ssh://path/to/new/repo.git
git push --tags ssh://path/to/new/repo.git

To complete the operations, I removed the temporary directory and refetched everything, just to be sure:

cd ..
rm -rf svn2git_tmpdir
git clone ssh://path/to/new/repo.git local_repo_dir

And voila, now you’re using GIT 🙂

1 comment July 28th, 2011

XFCE terminal problems

Do your XFCE terminals, if opened at very high resolutions, make your workspace transitions very slow (freezing the Desktop Environment for a couple of seconds)? I do not know if this a problem caused by vte, a terminal library shared with Gnome, or if it appears because of the new nVidia drivers.

Anyway, the solution is: disable terminal transparency

Simple (and bizarre) as that. 🙂

Add comment March 23rd, 2011

Working around OpenSSH 5.8 connection failures

If you currently have connection problems using OpenSSH 5.8 towards older installations, with errors like:
Read from socket failed: Connection reset by peer
even before the client/server key exchange and authentication, try appending the option:
-o KexAlgorithms="diffie-hellman-group-exchange-sha1"

This worked for me in a couple of old server installations (namely, OpenSSH_5.3p1 Debian-3ubuntu5).

Alternatively, add the following
KexAlgorithms diffie-hellman-group-exchange-sha1
to .ssh/config. Remember that you can restrict this option to only some hosts by using the line:
Host "hostpattern"

Add comment March 11th, 2011

At long last. No king rules forever, my son.

Lich King kill achievement

Lich King spoils

2 comments October 20th, 2010

Cataclysm Cinematic Intro released

Blizzard Entertainment released the cinematic introduction of the awaited World of Warcraft expansion, named Cataclysm, that will hit the stores on 7th December 2010.

Deathwing the Destroyer, that will take the place of the now defeated Lich King as the evil mastermind in the game, threatens the virtual world with its rage.

“Pain. Agony. My hatred burns through the cavernous deeps. The world heaves with my torment; its retched kingdoms quake beneath my rage. But at last, the whole of Azeroth will break and all will burn beneath the shadow of my wings.”

Add comment October 18th, 2010

(De)motivating WOW players

WOW demotivational

True story. That formula is 100% correct for hit capped, level 80 Warlocks.

Add comment June 29th, 2010

Summoned Beast Battle

Summoned Beast Battle (referred also as A Contest of Aeons), from the Official Soundtrack of Final Fantasy X.

Add comment October 16th, 2009

Automatically clean Purple (Pidgin, Finch) logs

If you, like me, log all of your IM conversations; if you, like me, use Pidgin or another client based on libpurple; if you, like me, have friends that often change their status line, generating useless log lines as

foo changed status from Busy to Busy @ whatever

If you think, as well as me, that 150 MB of logs are way too much; well this is the script for you.

Purple Logs Cleaner aims at removing redundant entries from system logs in textual format. It looks for the .system folders of all your Pidgin/Finch accounts and automatically removes lines according to some customizable patterns. By now, it removes lines in the form “… changed status from … to …”, where the starting and the final status are the same (both in the English and in the Italian translated version “… ha cambiato stato da … a …”); you can hack the sed line at will, but please send me patches 😉 . The script will not touch any other file and it won’t run (obviously) if Pidgin is active.

Back to the numbers: after sixteen minutes of cleaning (kinda slow, because I had to scan for both English and Italian patterns, as I had some problems with intltool in the past), my ~/.purple/logs directory size decreased from 159 MB to only 58 MB! But, more importantly, the .system subdirectories, whose content is the only one touched by the script, decreased from an aggregated size of 143 MB to approximately 40 MB, that is the removal of the 72% of the original content! Subsequent invocations are much faster, under ten minutes, because much of the cruft has already been removed.

Ok, this is enough 🙂 You can download the script HERE !

Comments are welcome 😉

Add comment September 4th, 2009

Previous Posts



February 2018
« Feb    


Posts by Month

Posts by Category

What's played in the cave