Time for a quick micro-post, I think. I feel like sharing two useful fragments of my git configuration.
First up, aliases. I have a few useful shortcuts defined, as well as some nice ways of displaying a repository’s history. I’ve aliased many of the common commands to two-letter versions which evoke the similar Subversion command aliases:
[alias]
st = status
di = diff
co = checkout
ci = commit
br = branch
sta = stash
graph = log --decorate --oneline --graph --all --date-order
lg = log --graph --pretty=format:'%C(yellow)%h%Creset -%C(yellow)%d%Creset %s %C(green)(%cr)%Creset %Cred<%an>%Creset' --abbrev-commit --date=relative --date-order
The last two aliases above provide a nice graphical view of history in the console. git graph displays all history of all branches in date order rather than topological order. This means that commits on different branches may be interleaved, rather than grouping commits on different branches. git lg displays a little more information (including author and relative timestamps), and allows me to pick which branches I want to see. The examples below are all taken from the Jerity repository.
-
-
git graph example, showing multiple branches
-
-
git graph example showing many branches
-
-
git lg example
The second tip is repository URL rewriting. This tackles the annoying problem of having submodules in projects that you want to be able to commit to, while making sure other people only see/use the read-only URLs. Git will very helpfully rewrite URLs from one form to another, so by having:
[url "ssh://git@github.com/dingram/"]
pushInsteadOf = git://github.com/dingram/
in my configuration, I can git clone git://github.com/dingram/repository and when I push, it will automatically push to git@github.com:dingram/repository instead. This can be verified using git remote -v. The only thing to beware of is the format: the replacement URL goes in the section header, and the pattern to be replaced appears in the section itself.
The scenario is that you have used git-svn to import an SVN repository, and you want to make use of the already-imported commits elsewhere. Unfortunately, git clone does not (currently) clone the git-svn information. It looks like we have to fully rebuild the git-svn repository, which would then mean pulling every commit from the Subversion server once again. What we’d really like to do is to make use of history we already have from git.
Quick start
For those who just want the commands and don’t want to wait:
git clone user@hostname.tld:/path/to/git-svn.git git-svn-clone
cd git-svn-clone
git svn init -s svn://hostname.tld/path/to/svn
git config svn.authorsfile $(basename $(pwd))/git-authors
rsync -avpP user@hostname.tld:/path/to/git-svn.git/svn .git/
git update-ref refs/remotes/trunk origin/master
git svn fetch --all && git svn rebase
Full details
So, what does all this do? Let’s look at it in stages.
- Clone the existing
git-svn repository, to get the history and avoid hitting the Subversion server any more than we need to (git clone)
- Set up the Subversion integration information (
git svn init)
- Set up the translation between Subversion authors (bare username) and git authors (name + email address) (
git config svn.authorsfile)
- Copy the Subversion branch metadata from the original
git-svn repository
- Create the local “trunk” reference that
git-svn will require
- Fetch any new revisions from Subversion (and update the revision map between git and Subversion), and then make sure that “master” points at the head of the Subversion trunk
Bonus tip
If you have a number of git branches, it can be a pain to keep rebasing them to the latest trunk (as Subversion doesn’t like non-linear history). This little script may help:
This will automatically rebase all of the branches onto master, although it won’t handle sub-branches very well.
I recently became curious about creating some edit-in-place controls: things that look like static text until you click them, and they magically become editable. It turns out that creating this sort of thing is almost trivial with jQuery, which is now my favourite JavaScript framework. I’m a big fan of functional-style programming, and jQuery plays right into that.
It was still surprising that the bulk of what I wanted to do can be done in about 16 lines of code. That’s right: sixteen.
The plan was to create an edit-in-place system that would degrade nicely in browsers with JavaScript disabled. This isn’t necessarily as elegant as it could be and it doesn’t yet handle all input types, but that’s what version one is for! So without further ado, I present the code:
$.fn.in_place_edit = function() {
this.each(function() {
var $eip = $('<span></span>');
var $el=$(this).hide().after($eip);
$eip.text($el.val());
$eip.click(function(){ $eip.hide(); $el.data('origval', $el.val()).show().focus().select(); });
$el.blur(function(){
if($el.is('select')) $el.data('origval', $el.val());
$eip.text($el.data('origval')).show(); $el.hide().val($el.data('origval'));
});
$el.keydown(function(e){
if (e.which==27) $el.val($el.data('origval')).blur();
if (e.which==13||e.which==9) {
e.preventDefault();
$el.data('origval', $el.val()).blur();
}
});
});
};
Usage:
$(function(){ $('input, select').in_place_edit(); });
So, what does all this do? First of all, we create a new function on the main jQuery object, called in_place_edit. This then iterates over elements matching the selector. It hides the input and creates a placeholder <span> element with the input’s value. Then we simply set up event handlers to deal with the placeholder being clicked, the input losing focus, and various keypresses (enter/tab to accept, esc to cancel). To see it in action, I’ve put together a rough-and-ready demo.
Planned future enhancements:
- Checkbox input types (display using the labels?)
- Radio input types
- File input types (if possible)
- Textareas
- Any other types…
Maybe further updates later on!
Note: This is a fairly rambling explanation of recent events. I assume that you have at least a passing knowledge of LVM and its terminology. This was written to prove that it is possible to recover from pvmove failing (in certain cases) due to the way it performs its operations and backs up metadata. Continue reading “Recovering from pvmove failure” »
Many hearing aids can handle direct audio input (DAI), often via a “shoe” that attaches to contacts on the aid itself. This shoe then provides a DAI jack (sometimes called a europlug or eurojack) that cables can be plugged into.
There seems to be a complete lack of cables designed for people with a single hearing aid, so one of my upcoming projects will be to convert a Y-cable that can serve two hearing aids into a joint DAI/earphone cable instead.
 DAI connector pinout
The DAI connector has the following pinout:
- short/thick pin: ground
- long/thin pin: VDD (apparently — doesn’t seem to actually be connected to anything on a 3.5mm cable)
- short/thin pin: signal
Remember that a standard 3.5mm audio plug has the following pinout:
- tip: left signal
- inner sheath: right signal
- outer sheath: ground
Next stage: connecting an earphone to the plug on one side of the cable, to see if there are any impedance issues, although the cable I am using (an fmGenie one) is a very low-impedance cable because I have an Oticon hearing aid. Measured with a multimeter, it seems to be around 0Ω, so I think that’s good enough for me. I believe attenuated cables have a 330kΩ resistor in series with each signal line (according to Neil Ferguson’s bluetooth hearing aid hack page).
My ultimate goal is to get hold of a DAI jack that I can solder directly to an old earphone, so that I can just plug the spare DAI cable into the earphone directly, almost as if it were a hearing aid itself. Unfortunately, it seems that it is impossible to get hold of such things. According to Connevans, DAI jacks are only custom-made for hearing aid shoes. After some discussion, it seems like I should be able to make one myself though (with some help!) so we shall have to see how that turns out.
I’ve been thinking recently about Insight again, and I’ve been considering part of the problem with naming and uniqueness.
Names in a traditional file system are made unique based on a full path to the file, but most people think of a file name as just the final component. This would then cause a problem with the move to Insight, as a file could appear in multiple directories, and its only distinguishing feature would be the final component of its path. This is counter-intuitive and can cause all sorts of problems.
Consider makefiles, for example. They rely on a standard named file (Makefile) appearing at various levels in the hierarchy in order to work. Obviously, you would want different makefiles at different levels and in different projects, but Insight as it stands has no way to handle this.
I then started thinking about what makes a file unique. In the end, I came up with two things: name and content. This covers the makefile case (same name, different content) as well as the backup case (same content, different name). It then occurred to me that, in the general case, all you need to distinguish a file is its content, and then actually finding it can all be left up to metadata.
Continue reading “A content-based file manager” »
I recently had to restore a server that failed to boot after a power cut. This machine was a Linux VMWare host, and it had three Linux guest virtual machines that were running at the time. While we had full backups available, I decided to set myself the challenge of recovering the entire images, to save the pain of a complete rebuild.
The host server partitions were LVM-formatted volumes on top of hardware RAID-1, and each of the virtual hosts were partitioned with LVM too, internally. This means that the restore process will not be at all trivial. With just a complete image of the host system, I would need to restore (deep breath) files on a partition on an LVM logical volume (inside a volume group, on a physical volume) in a VMWare hard disk stored on LVM (logical volume inside volume group of physical volumes) inside a disk image that is itself a file on a disk. How very convoluted.
I used a Gentoo system to restore the data, although any Linux system with the appropriate packages should be able to do it. No searches turned up information on doing all of this, and I had to come up with some of it myself, so I thought I would document the process.
Continue reading “Restoring from LVM and VMWare disks” »
I’ve begun the long and (hopefully) interesting task of working on mod_sqltemplate. I have not yet found a tutorial or guide to working with APR’s DBD API (the database abstraction layer for the Apache Portable Runtime), so I’ll write one and publish it here as I go along…
The number of projects I have in mind just keeps growing… I really need to get something together to organise them, and remember them! But here are two more to add to the list: an Apache module for dynamic configuration generation and a PHP framework inside an extension. Read on for a monster post with more information…
Continue reading “Modules for Apache and PHP” »
So I’ve decided now that, as I have some free time and I will soon have some disposable income, that it’s time to start on an idea that’s been brewing for a little while: HackWeekend. This is a radical departure from some of my previous ideas, in that it’s a social thing.
When we were coming to the end of our time at university (and consequently our time as housemates), my good friend Alex Yong and I decided that this should not be the end, and we should all get together regularly afterwards. As we technical types aren’t that good at small talk, we thought that rather than just meeting up and chatting, we should actually have an aim in mind. An independent idea from another friend (Dave Durant) around the same time was that he and I should get together for a weekend sometime with lots of Red Bull and pizza and very little sleep, and to see what we could code/prototype.
Continue reading “HackWeekend: an introduction” »
|
|