Sorry, LiveJournal, git bye and thanks for all the spam


I've been blogging elsewhere without announcing where it is to the public. The primary reason I left here is because the pages seem to get too many spam comments, and I got sick of removing them. I could have simply ignored all of them, but sometimes I get nice comments from satisfied and unsatisfied git users alike, and it would be rude of me to discard them without reading.

I haven't visited LiveJournal since I wrote about Git 1.7.5 release here, and was surprised to find that the look of the site somewhat has changed. It could be possible that the spam filtering at LiveJournal has become a lot better while I was looking the other way, but I do not care too much anymore.

In any case, I am leaving this site as I got comfortable enough writing at the new site now. Also I started to gain momentum again and am spending more time writing new code for the project than before. Life is too short to waste fighting blog comment spam.



Git 1.7.5


The cycle took a bit longer than I would have liked (83 days), but finally I tagged the latest release v1.7.5 with 547 changes from 77 contributors. The previous release v1.7.4 had 554 changes from 104 contributors and it took 134 days.

Changes are very well balanced: 20% in implementation, 20% in tests, 15% in documentation. There is nothing particularly earth-shattering but the foundation for i18n is now laid out which is internally a big thing. We also had a large update to git-gui's po files (pt_br).

On the development branch a handful of interesting and rule changing features have already been cooking. Hopefully the next cycle will be even shorter.

Due to comment spamming at this site, I am disabling comments on this entry. I might migrate out of livejournal altogether.


Un-fun with LiveJournal Spams


I've been getting many spam comments in my blog at LiveJournal. I have configured it to hide all the comments until I vet them for spams, and I thought everybody needs to solve captcha before posting a comment, so apparently either there are too many people with too much spare time, or captcha LiveJournal offers is severely broken.

Either way it is not fun. Perhaps it is time to relocate...

  • Current Mood
    annoyed annoyed

Fun with being at the Open Source Program Office

A few days ago, we had a group of young visitors. They are high-school kids in SF area who are learning Open Source as an extra-curricular activity. It was a pleasure to learn that these youngsters are enthusiastic about HTML5 and store their projects in git. We had a brief q&a session over lunch.

Google's Open Source Program Office (OSPO) runs a series of "Interviews" by Jeremy Allison (who works on Samba) on its YouTube channel, and I ended up participating in an episode. Chatting with Jeremy on git was fun (he was unusually kind on the tape, even though I know he constantly curses git when he is not being taped).

It was published in the Open Source Blog today.


Un-Fun with OS Update

Late in the evening on Sunday was a bad time to decide running "aptitude".

I have been happily running Debian Lenny but I forgot that I was actually tracking "stable" in /etc/apt/sources.list and they released Squeeze as stable. Many things started breaking:
  • I seem to be getting many "EDAC MC0: UE page 0x0, offset 0x0, grain 107..." errors, and this seems to be marked at kern.emerg level, splattering two lines of such logs every second to any tty I open. Tentatively told syslog to send kern.emerg to dustbin, but a quick Googling indicates that this is not coming from actual memory failure, but from a misconfigured and/or buggy BIOS. Need to try rebooting with "QuickBoot" turned off (whatever that is) when I get home.
  • The initial boot fails and drops me to the maintenance mode (requiring root login), but it is impossible to diagnose what is wrong due to the EDAC log messages coming from the kernel (there is no syslog at that stage, it seems). I suspect that this will become a non-issue once I sort the "/boot" partition issue (next item in this list) out.
  • My /boot partition is on /dev/md0 (RAID-1) across all physical disks; it doesn't seem to be detected at the boot time. It seems to have something to do with the suggestion the OS update procedure made to update /etc/mdadm/mdadm.conf file (it listed a wrong number of disks).
  • The host somehow lost its (fake) FQDN, causing many things to break, including:
    • my emacs configuration that changed behaviour on my home environment vs my work environment;
    • msmtp and leafnode (these want to see the host has FQDN for obvious reasons) refuse to run;
Added an entry for to work this around.
  • The (admittedly obscure) Japanese input method I use in Emacs (again) got broken;
  • Either the message mode in Emacs or msmtp changed and .emacs needed adjustment until I can send e-mails out again;
  • The Gnome UI has "Shutdown" immediately next to "Logout" on the System menu, which invited my wife to accidentally shut the box down while I was looking the other way. I need to find a way to hide this from users.

The moral of the story? There is actually none.

Unfortunately, no time is a good time to do a major OS update.

 [edit: March 8th, 2011]

My wife lost e-mail connectivity and it took embarrassingly long time to diagnose what went wrong. After wasting a lot of time clicking around to see what kind of configuration items are offered for the program, I decided to Google it, but I didn't know what that GUI e-mail thingy my wife uses is called (neither did she), as I don't use the GUI thingy myself. After figuring out that it is called evolution, I logged in to my wife's accout, opened a terminal and manually ran it from there, to be greeted by "evolution-shell-Message: Network disconnected. Forced offline."

It turns out that evolution was reading from NetworkManager and blindly trusting its misinterpreted version of what NetworkManager said and decided to gray out the Send/Receive GUI control. My network setting on the machine predates NetworkManager, configuring all the interface statically and manually, and everything runs just fine, even though the GUI Network thingy says "unmanaged". Even evolution itself, when asked to check what authentication methods are supported by outgoing smtp server in the outside world, talks to the outside world without paying attention to that "unmanged" status. It is criminally stupid not to understand the distinction between "unmanaged" and "not connected"--sheesh.

Uninstalling NetworkManager was all it took, as I don't need it on that box that does not have any dynamic network interfaces.


Nearing 1.7.4

I thought that 1.7.4 was going to be just another incremental update, but small things sometimes add up to form a surprisingly larger whole.

Here are some of the highlights since 1.7.3:
  • The structure of the discussion thread send-email creates when sending a re-rolled series (i.e. with In-Reply-To) is finally made much saner. Earlier, everything including the cover letter was made into a direct response to the previous round, but now only the cover letter becomes a direct response, and everything else becomes a response to the cover letter for the current round.
  • Bash-completion is usable with Bash-4, which broke completion of --option=with-value of our earlier implementation.
  • Tab-width used in whitespace breakage checking can be configured via the attributes mechanism. Earlier, we insisted that a Tab had to be 8 places everywhere.
  • The merge machinery can now be told to merge branches ignoring various whitespace changes.
  • The fetch command learned to recurse into submodules, reducing the need to use "submodule update". It will be a longer-term trend to roll submodule-awareness into more basic commands, and this is one of the steps in that direction.
  • <tree>:<path> notation to name a blob or a subtree can be told to take the current directory relative to the top of the current working tree by prefixing <path> part with "./", e.g. "HEAD:./Makefile" when you are in "drivers/" subdirectory names the blob at "drivers/Makefile" in the current commit.
  • Pickaxe search "log -S<string>", which was designed for scripted use, met a more human-friendly cousin "log -G<regexp>". While "-S<string>" is about counting the number of appearance of <string> in the file before and after the change and reporting when they differ, "-G<regexp>" looks at the actual patch text and reports if a line that matches <regexp> appears as either added or deleted, allowing detection of simply moving a matching line in a file, which "-S<string>" was not designed to do.
Reviewing the list of updates, you would notice (and hopefully, be pleasantly surprised) that there are quite a few user-visible usability enhancements.

  • Current Mood
    thankful warm and fuzzy
  • Tags

Fun with telling stories

Somebody wrote an end-user documentation that describes this command:
$ git reset HEAD^ -- file2
and said:

This brings us into a funny state. The command does not reset HEAD, and the contents for the file2 recorded in that commit is also in the working tree, but the index records contents from an older commit. Because the copy in the working tree and the contents in the HEAD are the same, "git commit -a" will not commit any change. Worse, "git diff" will report changes to the file. In order to commit from this state, you have to "git add" the file you just reset and then run "git commit".

There is no lie in what is said in the above, but it makes me sad that new users will be taught by people who would say things like this. They may know "Doing A causes effect B", but they do not teach "For X, you want to see B" in the first place. Without knowing why you want B, a new user would not understand why being able to do A to cause B is a good thing to begin with.

By setting the stage in a more appropriate way, you can turn the "funny state" misconception into a more positive experience. For example, here is how I would tell the same story:
You have been working on two files, file1 and file2, and made a commit to record changes to them. But you realized that the change is better done as two commits, first commit that updates file1 with a new infrastructure, and then the second commit that records the change to use the new infrastructure in file2 on top of that. Also, you are not entirely satisfied with what you wrote in file2 yet.

For the purpose of fixing the commit you just made, i.e. step 1, you would want to amend it in such a way that it does not have any change to file2. After amending, you would want to perfect the changes you started making to file2 in your working tree, and then make another commit on top of the amended commit to record that change, which would be your step 2.

How would you perform the first step of amending the current commit, without disrupting the unfinished work you have in file2 in your working tree, so that you don't have to re-type anything to file2 while working in your step 2?

"git reset HEAD^ -- file2" is the answer. It will prepare your index so that it has the same contents as the commit you just made, except for file2, whose contents you just took from the commit before that with this "reset" command. From that state, all you have to do is to "git commit --amend" without -a option. Before amending the commit, you will see nothing in "git diff HEAD^ file2" (because you do not want the HEAD to be rewritten to have any change to that file). By running "git diff file2", you can check the progress of your unfinished change to file2 that you are not going to include in your amended, first, commit.

After amending the commit, you will further work on file2, and then "git commit -a" or "git commit file2" to conclude the second step.
With such an understanding of what the command is for (i.e. "why you would want to see B?  Because you want to do X"), you would never write things like "git diff still shows the changes" or "committing from this state requires you to 'git add' the file again", as if they are problems to be worked around. These remarks are true but entirely miss the point, as you would actively want "diff" to show the changes and you would never "commit -a" that state, if you know what you are doing.

Perhaps the person who wrote the above passage does not understand what "reset HEAD^ -- path" is about. But then why is he teaching new people?

And that is the saddest part. The author of the above passage is supposed to be an expert who teaches other people, and I am sure there are plenty of other similar "experts" in the field.

When it comes to teaching people, WHY and WHAT FOR is much more important part of understanding than merely knowing HOW.

At least that is what I think, and that is why my Git book (the publisher said it is now at the fourth reprint) is full of descriptions on WHY and WHAT FOR.
  • Current Mood
    annoyed annoyed
  • Tags