Posts filed under 'Software'

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
  origin/awesome
  origin/master

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.

— NORMAL USERS, RESUME READING HERE —

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 😉

Preparation

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 <mail.address@example.com>
username2 = Name2 Surname2 <mail.address2@example.com>
(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
done

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);"' \
	--env-filter 'export GIT_COMMITTER_NAME="${GIT_AUTHOR_NAME}"; export GIT_COMMITTER_EMAIL="${GIT_AUTHOR_EMAIL}"; export GIT_COMMITTER_DATE="${GIT_AUTHOR_DATE}";' \
	-- --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

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

Emacs 23.1, bitches!

The first official 23.* version of the popular text editor Emacs has been released. Well, “text editor” is almost a reduction of functionality, as Emacs has thousands of commands to accomplish the most unthinkable tasks.

Emacs 23.1

From the official announcement:

Here are some new features of Emacs 23.

– Improved Unicode support (the internal character representation is now based on UTF-8).

– Font rendering with Fontconfig and Xft.

– Support for using X displays and text terminals in one session, and for running as a daemon.

– Shift-selection.

– Smarter minibuffer completion.

– Per-buffer text scaling.

– Directory-local variables.

– New packages for:
* viewing PDF and postscript files (Doc view mode)
* connecting to processes via D-Bus (dbus)
* using the GNU Privacy Guard (EasyPG)
* displaying line numbers in the fringe (Linum mode)
* editing XML documents with on-the-fly validation (nXML mode)
* editing Ruby programs (Ruby mode)
* display-based word wrapping (Visual Line mode)

3 comments July 31st, 2009

Why free software shouldn’t depend on Mono or C#

Some days ago, the Free Software Foundation published a short, very interesting article by Richard Stallman that claims, as summarized in the title, that the FOSS community should not pursue the patent-encumbered way of the compatibility with closed minds.

This is not to say that implementing C# is a bad thing. Free C# implementations permit users to run their C# programs on free platforms, which is good. […] The problem is not in the C# implementations, but rather in Tomboy and other applications written in C#. If we lose the use of C#, we will lose them too. That doesn’t make them unethical, but it means that writing them and using them is taking a gratuitous risk.

Full article here: http://www.fsf.org/news/dont-depend-on-mono

2 comments June 29th, 2009

Personal Gentoo overlay on github.com

It’s a few weeks now that I’m keeping my personal Gentoo overlay on github. I’m uploading there some ebuilds that I need, usually to fix bugs corrected only on Bugzilla, to bump recent packages or anything that is not yet in the official Portage tree or in any of the popular overlays that I use.

http://github.com/dark/darkGentooOverlay/tree/

If you wish to use it, just clone it somewhere in your disk with
git clone git://github.com/dark/darkGentooOverlay.git
and add the fetched folder to your PORTDIR_OVERLAY.
If you have any comments, please let me know 😉

Add comment June 20th, 2009

Avoid Skype crash with video conversation on Linux

There is a recurring problem that (used to) annoy me when I tried to use my webcam with Skype on Linux. Being a proud owner of a

00:02.1 Display controller: Intel Corporation 82852/855GM Integrated Graphics Device (rev 02)

the number of Xv ports that the display driver (xf86-video-intel) exports to the applications is quite limited:
$ xvinfo | grep ports
number of ports: 1

Yep, only one, not enough to show both the incoming and the outgoing video stream. Skype underlines the problem by printing
Xv ports available: 1
on the console and, most importantly, by crashing whenever I try a full-duplex video conversation.

The workaround I found this evening is quite simple and I wonder why my previous attempts were unable to hit the target:

  1. Establish the audio conversation with the counterpart.
  2. Enable my own video stream: I see the video thumbnail and the peer starts receiving my image.
  3. Disable the local visualization of my video stream: I no longer see the preview, but the counterpart still receives my video. More importantly, the video resource (the Xv port) is still held by the application, so the attempt to show a new video window, in this moment, would crash Skype.
  4. Stop streaming my own video: the peer no longer sees my image. Probably Skype releases the Xv port in this moment.
  5. Ask the peer to start streaming his/her image: Skype allocates the (now free) Xv port to the incoming video, thus showing the counterpart data.
  6. Restart my video stream: Skype remembers that I desired not to see my preview in the current session, so no allocation attempt takes place, thus no crash.

Maybe there are some variations of the algorithm that work as well, but that’s enough for me 🙂 (and this method is almost transparent to the counterpart).

3 comments April 17th, 2009

Bash 4.0 released

The fourth major version of the popular Unix shell, bash, has been released.

This release fixes all the outstanding bugs and introduces some new functionalities: associative arrays, improvements to the programmable completion functionality, case-modifying word expansions, co-processes, support for the ‘**’ special glob pattern (that matches all directories and files within them, when appropriate, recursively) and additions to the shell syntax and redirections (like ‘|&’ as a synonym for ‘2>&1 |’, that I use frequently).
You can read the official announcement here.

Source: http://lwn.net/Articles/320353/

1 comment February 24th, 2009

Previous Posts


Rate:  

Calendar

November 2017
M T W T F S S
« Feb    
 12345
6789101112
13141516171819
20212223242526
27282930  

Badges

Posts by Month

Posts by Category

What's played in the cave