SaltyCrane: githttps://www.saltycrane.com/blog/2017-05-27T14:37:45-07:00git worktree notes
2017-05-27T14:37:45-07:00https://www.saltycrane.com/blog/2017/05/git-worktree-notes/<p>
<a href="https://git-scm.com/docs/git-worktree">
<code>git worktree</code></a>
allows you to have multiple working directories associated with one git repo.
It has been useful for me to look at, copy code between, and run two different
branches of my code. I learned about git worktreee from James Ide's tweet:
</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Have you ever needed to pause & switch branches to fix an urgent bug or check out a release branch? This all goes away with "git worktree".</p>— James Ide (@JI) <a href="https://twitter.com/JI/status/804232725766864896">December 1, 2016</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<h4>Initial setup</h4>
<p>Move the checked out git repository to a <code>/main</code> subdirectory</p>
<pre class="console">
$ mv /my-project /main
$ mkdir /my-project
$ mv /main /my-project
</pre>
<h4>Create a new working tree from an existing branch</h4>
<pre class="console">
$ cd /my-project/main
$ git worktree add ../my-branch-working-dir my-branch
$ cd ../my-branch-working-dir
</pre>
<h4>Create a new branch and new working tree</h4>
<pre class="console">
$ cd /my-project/main
$ git worktree add -b my-new-branch ../my-new-branch-working-dir origin/master
$ cd ../my-new-branch-working-dir
</pre>
<h4>Delete a working tree</h4>
<pre class="console">
$ cd /my-project
$ rm -rf my-branch-working-dir
$ git worktree prune
</pre>
<h4>fatal: my-branch is already checked out error</h4>
<p>
Deleting <code>.git/worktrees/my-branch</code> fixed the problem for me.
See <a href="https://stackoverflow.com/q/33296185/101911">https://stackoverflow.com/q/33296185/101911</a>
</p>
<h4>Reference / See also</h4>
<a href="https://github.com/blog/2042-git-2-5-including-multiple-worktrees-and-triangular-workflows">
https://github.com/blog/2042-git-2-5-including-multiple-worktrees-and-triangular-workflows
</a>
Converting an hg repository to git
2014-12-03T11:01:46-08:00https://www.saltycrane.com/blog/2014/12/converting-hg-repository-git/<p>From <a href="http://stackoverflow.com/questions/16037787/convert-mercurial-project-to-git">http://stackoverflow.com/questions/16037787/convert-mercurial-project-to-git</a>, use fast-export.</p>
<pre>
cd ~/src/bb
git clone git://repo.or.cz/fast-export.git
git init chrisatlee-poster-git
cd chrisatlee-poster-git
../fast-export/hg-fast-export.sh -r ../chrisatlee-poster
git checkout HEAD
</pre>
Git submodule notes
2013-03-07T11:21:12-08:00https://www.saltycrane.com/blog/2013/03/git-submodule-notes/<h4 id="add-new">How to add a new git submodule</h4>
<pre class="console">$ cd /home/eliot/path/to/main/project
$ mkdir -p lib
$ git submodule add git@github.com:saltycrane/another-project.git lib/another-project
$ git commit -m 'Add another-project git submodule' </pre>
<h4 id="references">Reference</h4>
<p><a href="http://chrisjean.com/2009/04/20/git-submodules-adding-using-removing-and-updating/">http://chrisjean.com/2009/04/20/git-submodules-adding-using-removing-and-updating/</a></p>
<h4 id="remove">How to remove a git submodule</h4>
<p>Via <a href="http://stackoverflow.com/a/1260982/101911">Stack Overflow</a> via
<a href="https://git.wiki.kernel.org/index.php/GitSubmoduleTutorial#Removal">Git Submodule Tutorial</a>.
<pre>
Delete the relevant section from the .gitmodules file.
Delete the relevant section from .git/config.
Run git rm --cached path_to_submodule (no trailing slash).
Commit
Delete the now untracked submodule files
rm -rf path_to_submodule
</pre>
</p>
Example using git bisect to narrow in on a commit
2011-08-13T08:48:21-07:00https://www.saltycrane.com/blog/2011/08/example-using-git-bisect-narrow-commit/<p>
I learned about
<a href="http://book.git-scm.com/5_finding_issues_-_git_bisect.html"><code>git bisect</code></a>
from this Stack Overflow poll:
<a href="http://stackoverflow.com/questions/347901/what-are-your-favorite-git-features-or-tricks/348461#348461"><em>What are your favorite git features or tricks?</em</a>
I thought it was so cool that I wanted to share an example.
</p>
<p>
After upgrading from Django 1.2.3 to Django 1.3, something broke on the website
I was working on. To figure out what was wrong, I used <code>git bisect</code>
to find the Django revision that introduced the relevant change. I cloned the
<a href="https://github.com/django/django">Django github repo</a> and
<code>pip install -e</code>'d it into my virtualenv. Then
I used git bisect as follows:
</p>
<ul>
<li>Start git bisect
<pre class="console">$ git bisect start </pre>
<pre class="console">$ git bisect bad 1.3 </pre>
<pre class="console">$ git bisect good 1.2.3
Bisecting: a merge base must be tested
[618153bd3b047529f6cfb50917c88270f30e8ea8] Fixed #10843: the textile tests now pass against the latest textile library.</pre>
<p>Note: <code>1.3</code> and <code>1.2.3</code> are git tags in the Django git repo.
Commit SHA1 hashes can be used instead.
</p>
</li>
<li>Start the development server in another terminal. Load the webpage in the browser. The page loads without error.
<pre>[04/Aug/2011 19:13:20] "GET /my/webpage/ HTTP/1.1" 200 16279</pre></li>
<li>Mark the revision good
<pre class="console">$ git bisect good
Bisecting: 774 revisions left to test after this (roughly 10 steps)
[39591cddccffdf3b66cfaaa60b95257daa4ef8c5] Fixed #14781 - Setting "CACHE_PREFIX" should be "CACHE_KEY_PREFIX". Thanks to adamv for report and patch.</pre>
</li>
<li>Reload the page. This time it throws a 500 error.
<pre>[04/Aug/2011 19:13:59] "GET /my/webpage/ HTTP/1.1" 500 118861</pre>
</li>
<li>Mark the revision bad
<pre class="console">$ git bisect bad
Bisecting: 387 revisions left to test after this (roughly 9 steps)
[6630bd24f45c7967c49b90adf82c63dd7d93e6f7] Fixed #13863 -- Corrected decimal separator in Swedish format module. Thanks, Ulf Urdén.</pre>
</li>
<li>Reload
<pre>[04/Aug/2011 19:15:45] "GET /my/webpage/ HTTP/1.1" 500 117536</pre>
</li>
<li>Mark the revision bad
<pre class="console">$ git bisect bad
Bisecting: 193 revisions left to test after this (roughly 8 steps)
[4d19282beb19b95e73aec119b40ed40456065a21] Migrated custom_methods doctests. Thanks to Alex Gaynor.</pre>
</li>
<li>Etc...
<pre>[04/Aug/2011 19:16:17] "GET /my/webpage/ HTTP/1.1" 500 117536</pre>
<pre class="console">$ git bisect bad
Bisecting: 96 revisions left to test after this (roughly 7 steps)
[ed63689b9e3be80c3af51bfc5d6805bcedbae9f0] Added file missing from r13590.</pre>
<pre>[04/Aug/2011 19:16:46] "GET /my/webpage/ HTTP/1.1" 200 16279</pre>
<pre class="console">$ git bisect good
Bisecting: 48 revisions left to test after this (roughly 6 steps)
[2eca0cd7f5fe6efd1f177724a948cdde7475f54c] Fixed #13754 - Add a note about a test client session property gotcha</pre>
<pre>[04/Aug/2011 19:17:12] "GET /my/webpage/ HTTP/1.1" 200 16279</pre>
<pre class="console">$ git bisect good
Bisecting: 24 revisions left to test after this (roughly 5 steps)
[d7e3c7bad40e5f66169b8b951d74c87103ece07d] Fixed #13095 -- `formfield_callback` keyword argument is now more sane and works with widgets defined in `ModelForm.Meta.widgets`. Thanks, hvdklauw for bug report, vung for initial patch, and carljm for review.</pre>
<pre>[04/Aug/2011 19:17:31] "GET /my/webpage/ HTTP/1.1" 200 16279</pre>
<pre class="console">$ git bisect good
[I forgot to copy/paste the console output for this one]</pre>
<pre>[04/Aug/2011 19:17:54] "GET /my/webpage/ HTTP/1.1" 500 117536</pre>
<pre class="console">$ git bisect bad
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[622bf3b2199e5e7015edccb00f1ab694291ca121] Fixed #11905: Raise an error on model form creation if a non-existent field was listed in fields. Thanks ben and copelco.</pre>
<pre>[04/Aug/2011 19:18:17] "GET /my/webpage/ HTTP/1.1" 500 117536</pre>
<pre class="console">$ git bisect bad
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[57427e9d758eb37b43f6b7804b24c6f47c2fa456] Fixed a test so that it actually tests what it's supposed to test.</pre>
<pre>[04/Aug/2011 19:18:37] "GET /my/webpage/ HTTP/1.1" 200 16279</pre>
<pre class="console">$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[dcb12158881cdcc619de0ae6d3f6cf674a0d4abb] Better error message for calling get_next_by_* on unsaved models. Patch from Marc Fargas. Fixed #7435.</pre>
<pre>[04/Aug/2011 19:19:07] "GET /my/webpage/ HTTP/1.1" 200 16279</pre>
</li>
<li>After marking the last commit, git bisect shows the first bad commit as 622bf3b2199e5e7015edccb00f1ab694291ca121
<pre class="console">$ git bisect good
622bf3b2199e5e7015edccb00f1ab694291ca121 is the first bad commit
commit 622bf3b2199e5e7015edccb00f1ab694291ca121
Author: kmtracey <kmtracey@bcc190cf-cafb-0310-a4f2-bffc1f526a37>
Date: Sat Sep 11 01:39:16 2010 +0000
Fixed #11905: Raise an error on model form creation if a non-existent field was listed in fields. Thanks ben and copelco.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@13739 bcc190cf-cafb-0310-a4f2-bffc1f526a37
:040000 040000 87ec1601b970938b55382a5aa66db74716552c3d 2d418dfe8dd9f67fea408e022aa13838086ce33b M django
:040000 040000 054e6f42b3b467e47f295f8fda6cdc8a7f2c054c 52ba5265ba9d6458f23c8cb4a8a9bdcdbfc1f590 M tests</pre>
</li>
</ul>
<p>Note: checking for failed unit tests instead of checking for a 500 error in the browser
is another (probably better) way to test with <code>git bisect</code>.
</p>
<p>Note 2: The problem with my code was that I was adding extra fields to a model
formset in the wrong way. I was trying to use <code>add_fields</code> on a base
model formset instead of creating a custom Form with the extra field
and specifying it in the factory. This
<a href="http://stackoverflow.com/questions/4727732/django-add-field-to-model-formset/4727913#4727913">Stack Overflow answer</a>
solved the problem for me.
</p>
<h4>Extra details</h4>
<p>Here's how I installed Django from github</p>
<ul>
<li>Clone the Django repo and <code>pip install -e</code> it in my virtualenv
<pre class="console">$ git clone https://github.com/django/django.git django-github
$ cd django-github
$ workon myenv
$ pip install -e ./ </pre>
</li>
<li>In another terminal run the Django development server
<pre class="console">$ cd /myproject
$ workon myenv
$ python manage.py runserver </pre>
</li>
</ul>
git notes
2011-08-11T10:09:40-07:00https://www.saltycrane.com/blog/2011/08/git-notes/<h4>How to get the tag associated with a specific git revision</h4>
<pre class="console">$ git describe --tags 5c70d1a15a4637a2057b1464c54820629e78cd05
staging/1.5</pre>
<h4>How to show the tracked branches from the remote "origin"</h4>
<pre class="console">$ git remote show origin </pre>
<h4 id="find-renames">How to find renames</h4>
<pre class="console">$ git log --name-only --follow --all -- filename </pre>
<h4 id="remove-tags">How to remove all local tags</h4>
<p>From <a href="http://stackoverflow.com/questions/1841341/remove-local-tags-that-are-no-longer-on-the-remote-repository/5373319#5373319">http://stackoverflow.com/questions/1841341/remove-local-tags-that-are-no-longer-on-the-remote-repository/5373319#5373319</a></p>
<pre class="console">$ git tag -l | xargs git tag -d </pre>
<h4 id="subdirectory-to-repo">How to detach a subdirectory into separate Git repository</h4>
<p>Note I did not want any tags or branches in the new repository.
From <a href="http://stackoverflow.com/questions/359424/detach-subdirectory-into-separate-git-repository/359759#359759">http://stackoverflow.com/questions/359424/detach-subdirectory-into-separate-git-repository/359759#359759</a>
</p>
<pre class="console">$ git clone --no-hardlinks /XYZ /ABC
$ cd /ABC
$ git remote rm origin
$ git tag -l | xargs git tag -d
$ git filter-branch --subdirectory-filter ABC HEAD
$ git reset --hard
$ rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --aggressive --prune=now </pre>
<h4 id="convert-hg-git">How to convert a Mercurial repo to git</h4>
<p>From
<a href="http://hedonismbot.wordpress.com/2008/10/16/hg-fast-export-convert-mercurial-repositories-to-git-repositories/">
http://hedonismbot.wordpress.com/2008/10/16/hg-fast-export-convert-mercurial-repositories-to-git-repositories/
</a>
</p>
<pre class="console">$ git clone git://repo.or.cz/fast-export.git
$ mkdir new_git_repo
$ cd new_git_repo
$ git init
$ /path/to/hg-fast-export.sh -r /path/to/hg_repo
$ git checkout HEAD</pre>
<h4 id="create-patch">How to create a patch for a single commit</h4>
<p>
References: <a href="http://stackoverflow.com/questions/6658313/generate-a-git-patch-for-a-specific-commit">http://stackoverflow.com/questions/6658313/generate-a-git-patch-for-a-specific-commit</a>,
<a href="http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git/">http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git/</a>.
</p>
<pre class="console">$ git format-patch -1 01434ee4fe056e384decbf2d398cccafe53120f2 --stdout > mypatch </pre>
<h4 id="breakup-commit">How to break up a previous commit into more than one commit</h4>
<p>
<a href="http://stackoverflow.com/questions/6217156/how-to-break-a-previous-commit-into-multiple-commits">http://stackoverflow.com/questions/6217156/how-to-break-a-previous-commit-into-multiple-commits</a>
</p>
<pre>
git rebase -i will do it.
To split apart your most recent commit, then:
$ git reset HEAD~
Now commit the pieces individually in the usual way, producing as many commits as you need.
If it was farther back in the tree, then
$ git rebase -i HEAD~3
where 3 is how many commits back it is.
When you get the rebase edit screen, find the commit you want to break apart. At the beginning of that line, replace "pick" with "edit". Save the buffer and exit. Rebase will now stop just after the commit you want to edit. Then:
$ git reset HEAD~
Commit the pieces individually in the usual way, producing as many commits as you need, then
$ git rebase --continue
</pre>
<h4 id="replace-master-branch">How to replace the master branch with another branch</h4>
<p><a href="http://stackoverflow.com/questions/2862590/how-to-replace-master-branch-in-git-entirely-from-another-branch">http://stackoverflow.com/questions/2862590/how-to-replace-master-branch-in-git-entirely-from-another-branch</a>
<pre>git checkout seotweaks
git merge -s ours master
git checkout master
git merge seotweaks</pre>
<p>Commit message when I did this at work:</p>
<pre>Replace old "master" with "dp.2013.r21" using
http://stackoverflow.com/questions/2862590/how-to-replace-master-branch-in-git-entirely-from-another-branch
git checkout dp.2013.r21
git merge -e -s ours master (that's where I am right now)
git checkout master
git merge dp.2013.r21
git push origin master
Cleanup:
git branch -D dp.2013.r21
git checkout dp.2013.r21
The automatically generated merge message:
Merge branch 'master' into dp.2013.r21</pre>
</p>
<h4 id="exclude-files-git-diff">How to exclude files from "git diff"</h4>
<p>There are 2 options:</p>
<ol>
<li>Use <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes">.gitattributes</a>
as described here: <a href="http://stackoverflow.com/a/1017676/101911">
http://stackoverflow.com/a/1017676/101911</a></li>
<li>Use new <a href="http://stackoverflow.com/a/21079437/101911">pathspec magic</a>
described here: <a href="http://stackoverflow.com/a/29374503/101911">http://stackoverflow.com/a/29374503/101911</a>
Example:
<pre class="console">$ git diff --stat=120,120 HEAD~10 | wc -l
68
$ git diff --stat=120,120 HEAD~10 -- '*/_assets/built/*' 'tests/robot/*' | wc -l
49
$ git diff --stat=120,120 HEAD~10 -- . ':!*/_assets/built/*' ':!tests/robot/*' | wc -l
20
</pre>
(The count is off by one because there is an extra line in the output.)
I will use this option because I can use it with <a href="https://github.com/jeffkaufman/icdiff">icdiff</a>
which shows whitespace changes.
</li>
</ol>
Colorized, interactive "git blame" in Emacs: vc-annotate
2011-05-28T10:57:28-07:00https://www.saltycrane.com/blog/2011/05/colorized-interactive-git-blame-emacs-vc-annotate/<a href="https://picasaweb.google.com/lh/photo/KIF7W9K8-RwAC_geRR7eYg?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/-A7iKHU0dAxc/TeEzuqkSKhI/AAAAAAAAAZM/mQSYYmCJQVU/s400/vc-annotate-emacs.png" height="382" width="400" /></a>
<p>A few months ago, I learned that
<a href="http://www.gnu.org/software/libtool/manual/emacs/Old-Revisions.html">
vc-annotate
</a> displays a nicely colorized
<a href="http://www.kernel.org/pub/software/scm/git/docs/git-blame.html">
<code>git blame</code></a> in Emacs.
Today I learned that it is also interactive. I can cycle through revisions
using <code>p</code> and <code>n</code>, open the file at a specified revision
with <code>f</code>, view the log with <code>l</code>, and show a diff
with <code>d</code> or changeset diff with <code>D</code>. (Unfortunately,
the diff is ugly and not in color.)
</p>
<p><code>vc-annotate</code> is included with Emacs. To use, open a version controlled file, and type <code>C-x v g</code> or
<code>M-x vc-annotate</code>
</p>
<p>I am using Emacs 23.1 on Ubuntu Maverick</p>
Versioning /etc with etckeeper and git
2011-04-24T13:29:27-07:00https://www.saltycrane.com/blog/2011/04/versioning-etc-etckeeper-and-git/<p><em>Update 2011-08-13</em>: I switched to a custom apt-get wrapper so that I can keep a versioned list of
installed packages and generally because I have NIH. (I had no problems with etckeeper). My apt-get wrapper
is on <a href="https://github.com/saltycrane/homedir/blob/master/bin/apt-get.py">here on github</a>
</p>
<ul>
<li><a href="http://kitenet.net/~joey/code/etckeeper/">etckeeper</a></li>
<li><a href="http://git.kitenet.net/?p=etckeeper.git;a=blob;f=README;h=ff3f82ce6dcbdd9d95c165eca88b965848d7f88b;hb=refs/heads/master">
etckeeper documentation (README)
</a></li>
</ul>
<ul>
<li>
<pre class="console">$ sudo apt-get install etckeeper </pre>
</li>
<li>Edit <code>/etc/etckeeper/etckeeper.conf</code>. Change VCS from "bzr" to "git"
</li>
<li>Initialize etckeeper and git repo
<pre class="console">$ cd /etc
$ sudo etckeeper init
$ sudo git status
$ sudo git commit -m 'Initial commit' </pre>
</li>
<li>Done.</li>
</ul>
My software tools list
2007-08-10T13:32:00-07:00https://www.saltycrane.com/blog/2007/08/current-configuration/<style type="text/css">
td {
vertical-align: top;
}
</style>
<p>Inspired by Mark Pilgrim's
<a href="http://web.archive.org/web/20101214224709/http://diveintomark.org/archives/2006/06/26/essentials-2006">
2006 Essentials list</a>,
below is a list of my current software tools. If you notice a lot of
"I switched from ..." statements, keep in mind that I am a
<a href="http://undefined.com/ia/2006/10/10/the-fourteen-types-of-programmers-type-2-those-that-like-shiny-things/">
programmer who likes shiny things</a>.
</p>
<h4 id="other-lists">Other lists</h4>
<ul>
<li><a href="http://web.archive.org/web/20101214234142/http://diveintomark.org/archives/2008/10/28/essentials-2008">
Mark Pilgrim's Essentials, 2008 edition</a>
</li>
<li><a href="http://web.archive.org/web/20081226033542/http://adam.gomaa.us/blog/essentials-cop-out/">
Adam Gomaa's Essentials (2008)</a>
</li>
<li>Here is a <a href="http://mark.pilgrim.usesthis.com/">2010 update
for Mark Pilgrim</a>. After 2 and a half years, I still have several items
in common: <a href="#operating-system">Ubuntu</a> running <a href="#terminal">rxvt-unicode</a>
and <a href="#editor">Emacs 23</a>, the <a href="#keyboard">Unicomp keyboard</a>,
an <a href="#mobile-phone">Android phone</a>, <a href="#email">Gmail</a>,
Google Reader, Google Docs, and Pandora.
</li>
<li><a href="http://salvatore.sanfilippo.usesthis.com/">Salvatore Sanfilippo on usesthis.com (2011)</a></li>
<li><a href="http://aaron.boodman.usesthis.com/">Aaron Boodman on usesthis.com (2011)</a></li>
</ul>
<h4 id="contents">Contents</h4>
<table>
<tr>
<td>
<ul>
<li><a href="#operating-system">Operating System</a>: Ubuntu</li>
<li><a href="#window-manager">Window Manager</a>: Qtile</li>
<li><a href="#editor">Editor</a>: Emacs</li>
<li><a href="#terminal">Terminal</a>: urxvt + screen</li>
<li><a href="#vcs">Version Control System</a>: Git</li>
<li><a href="#high-high-level-language">"High-high-level" Language</a>: Python</li>
<li><a href="#web-framework">Web Framework</a>: Django/Flask</li>
</ul>
</td>
<td>
<ul>
<li><a href="#web-browser">Web Browser</a>: Firefox</li>
<li><a href="#email">Email</a>: Gmail</li>
<li><a href="#graphical-diff">Graphical Diff</a>: KDiff3</li>
<li><a href="#keyboard">Keyboard</a>: Leopold Tenkeyless (MX Browns)</li>
<li><a href="#office-chair">Office Chair</a>: Undecided</li>
<li><a href="#mobile-phone">Mobile Phone</a>: Motorola Droid 4</li>
</ul>
</td>
</tr>
</table>
<h4 id="my-list">My software tools list</h4>
<table style="font-size:100%">
<tr>
<td ><b>Category</b></td>
<td ><b>Currently using</b></td>
<td ><b>Comments</b></td>
</tr>
<tr>
<td id="operating-system" ><p>Operating System</p>
<a href="#operating-system" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://www.ubuntu.com">Ubuntu</a> 14.04 Trusty Tahr</p>
</td>
<td >
<p>My first
Ubuntu install was in 2007 (dual-boot) and I got my first Windows-free machine
in 2008. I have used Cygwin
and coLinux when on Windows. Cygwin integrates better with Windows applications,
but coLinux is super fast and allows you to run a full Linux distro on top of
Windows. Windows does have some advantages, but overall I prefer Linux.</p>
<p><em>Update 2008-09</em>: Switching jobs means I can now use Linux at work.
I'm now using Linux about 90% of the time. My wife still uses Windows Vista on our laptop.</p>
<p>I don't have enough experience
with OSX to draw any authoritative conclusions, though I think
<a href="http://en.wikipedia.org/wiki/Mark_Pilgrim">Mark Pilgrim</a>
has <a href="http://diveintomark.org/archives/2006/06/02/when-the-bough-breaks">
biased me against Apple</a>. Also, I think Linux's
<a href="http://c2.com/cgi/wiki?FreeAsInBeer">free as in beer</a> (and somewhat
related free as in speech) characteristics
vs. Mac's expensive (and somewhat related proprietary) characteristics
resonate with the cheap engineer in me.</p>
<p>Additional Linux vs. Mac commentary:</p>
<ul>
<li>
<a href="http://en.wikipedia.org/wiki/Jamie_Zawinski">JWZ</a> 2000:
<a href="http://www.jwz.org/doc/linux.html">Unix/linux sucks less, but it still sucks.</a>
</li>
<li>
JWZ <a href="http://jwz.livejournal.com/494040.html">2005</a>,
<a href="http://jwz.livejournal.com/780264.html">2007</a>: Linux sucks more.
</li>
<li>
<a href="http://en.wikipedia.org/wiki/Paul_Graham">Paul Graham</a> 2005:
<a href="http://www.paulgraham.com/mac.html">Return of the Mac.</a>
</li>
<li>
Mark Pilgrim 2006: <a href="http://diveintomark.org/archives/2006/05/30/bye-apple">
Bye, Apple</a>
</li>
<li>
<a href="http://en.wikipedia.org/wiki/Cory_Doctorow">Cory Doctorow</a> 2006:
<a href="http://www.boingboing.net/2006/06/29/mark-pilgrims-list-o.html">
Me too</a>.
</li>
<li>
<a href="http://en.wikipedia.org/wiki/Tim_Bray">Tim Bray</a> 2006:
<a href="http://www.tbray.org/ongoing/When/200x/2006/06/15/Switch-From-Mac">Me too</a>,
<a href="http://www.tbray.org/ongoing/When/200x/2006/08/16/Back-to-the-Mac">Back to the Mac</a>
</li>
<li>
Steve Yegge 2008:
<a href="http://steve-yegge.blogspot.com/2008/04/settling-osx-focus-follows-mouse-debate.html">
Switching to OSX for the fonts</a>
</li>
<li>
Of course, <a href="http://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a>
<a href="http://www.smh.com.au/news/technology/q-and-a-with-linus-torvalds/2008/02/05/1202090403120.html?page=2">
"prefers" Linux</a> (2008)
</li>
<li><a href="http://en.wikipedia.org/wiki/Donald_Knuth">Donald Knuth</a>,
author of <em>The Art of Computer Programming</em>,
<a href="http://www.informit.com/articles/printerfriendly.aspx?p=1193856">
uses Ubuntu Linux for work, and Macs for play</a> (2008).
</li>
<li>Salvatore Sanfilippo (author of <a href="http://code.google.com/p/redis/">Redis</a>)
chooses to use
a Mac so he can <em>"focus on what <he's> doing without spending hours trying to
fix unrelated desktop stuff"</em> but says Linux is
<a href="http://antirez.com/post/linux-better-for-coding.html">
<em>"still better for coding"</em></a> (2009).
</li>
<li>Ted Dziuba: <a href="http://harmful.cat-v.org/software/operating-systems/osx/osx-unsuitable-web-development">
<em>MacOS X is an Unsuitable Platform for Web Development</em>
</a> (2011)</li>
<li>Bozhidar Batsov: <a href="http://batsov.com/Linux/Windows/Rant/2011/06/11/linux-desktop-experience-killing-linux-on-the-desktop.html">
<em>The Linux desktop experience is killing Linux on the desktop</em>
</a> (2011)</li>
</ul>
<p>History: 1987: <a href="http://en.wikipedia.org/wiki/Apple_IIGS">Apple GS/OS</a>,
1994: <a href="http://en.wikipedia.org/wiki/Windows_3.1x">Windows 3.1</a>,
2000: <a href="http://en.wikipedia.org/wiki/Windows_98">Windows 98</a>,
2001: <a href="http://en.wikipedia.org/wiki/Windows_XP">Windows XP</a>,
2007: <a href="http://en.wikipedia.org/wiki/Windows_Vista">Windows Vista</a>,
2007: <a href="http://en.wikipedia.org/wiki/Ubuntu_%28operating_system%29">Ubuntu</a>
</p>
</td>
</tr>
<tr>
<td id="window-manager"><p>Window Manager</p>
<a href="#window-manager" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://www.qtile.org/">Qtile</a></p></td>
<td >
<p>The WM written in Python,
<a href="http://panela.blog-city.com/fun_of_tiling_window_managers.htm">
recommended by Matt Harrison</a>.
</p>
<p>Previously, wmii: dynamic, tiling, scriptable window manager that doesn't
require a mouse. It sucks less.</p>
<p>I switched from <a href="http://www.nongnu.org/ratpoison/">ratpoison</a>
at the same time I started using coLinux because running native Linux
allowed me to use any Linux window manager as well.</p>
<p>Recently, some have switched from wmii to
<a href="http://xmonad.org/">xmonad</a>, the new
<a href="http://www.haskell.org/">Haskell</a> tiling window manager.
It has some nice features over wmii, including dual head support, but after
a brief excursion, I slightly prefer wmii's way of doing things.</p>
<p>If you're a hard core Lisper,
<a href="http://www.nongnu.org/stumpwm/">stumpwm</a> is the window manager
for you. It has a <a href="http://en.wikipedia.org/wiki/REPL">REPL</a>. This one
seems a little too hard core for me, especially since I don't know Lisp.</p>
<p>History: 2007: ratpoison, 2007: wmii, 2012: Qtile</p>
</td>
</tr>
<tr>
<td id="editor"><p>Editor/IDE</p>
<a href="#editor" title="Section permalink" class="sectionlink">¶</a></td>
<td><p><a href="http://www.gnu.org/software/emacs">GNU Emacs</a> 24.3</p></td>
<td >
<p>Switched from Eclipse in 2007. It was a slow transition, but
I think Emacs is worth the investment.</p>
<p><b>On Emacs vs. Vim:</b> I really like that Vim can be used easily on remote
machines. Currently, I use TRAMP for remote file editing. It is very cool,
but it is slow, and I sometimes fall back on nano (*gasp*) for a quick
config file edit when I am logged into a remote terminal. I also suspect
that the dual modes of Vim are more efficient than Emacs-- I'm just not
smart enough to get used to it. Maybe someday I will switch to
<a href="http://www.gnu.org/software/emacs/manual/html_node/viper/index.html#Top">Viper
mode</a>. Why Emacs over Vim? I choose Emacs because it is more powerful
and closer to an IDE. Emacs Lisp allows you to do whatever you want.
</p>
<p><b>On Emacs vs. Eclipse:</b> I found Eclipse was too slow and heavy, used too
much screen real estate, and was too difficult to customize. Scripting
Eclipse required writing extensions in Java whereas Emacs can be extended
in elegant Lisp. I think Eclipse (and other IDE's) are better for code
exploration and they probably have features that I'm not aware of since
I don't use them. I figure, though, that with enough Emacs Lisp, Emacs
can do anything those IDEs can do. If you really want those features,
it's a question of if you want to spend the time achieving perfection
in Emacs or getting real work done in another IDE. I choose perfection. ;)
</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://blog.ianbicking.org/the-vs-emacs.html">
THE vs. Emacs</a>, Ian Bicking (2005)</li>
<li><a href="http://steve.yegge.googlepages.com/effective-emacs">
Effective Emacs</a>, Steve Yegge (2005)</li>
<li><a href="http://blog.ianbicking.org/other-editors.html">
Other Editors?</a>, Ian Bicking (2005)</li>
<li><a href="http://glyph.twistedmatrix.com/2008/04/structured-python-editor.html">
Structured Python Editor</a>, Glyph Lefkowitz (2008)</li>
<li><a href="http://chalain.livejournal.com/74234.html">
Editor Wars: Revenge of the... oh, whatever.</a>, Chalain (2008)</li>
<li><a href="http://metajack.im/2008/09/05/what-you-can-learn-from-emacs/">
What You Can Learn From Emacs</a>, Jack Moffitt (2008)</li>
<li><a href="http://glyph.twistedmatrix.com/2008/12/emacs-test.html">
The Emacs Test</a>, Glyph Lefkowitz (2008)</li>
<li><a href="http://www.redreddesign.com/blog/emacs-extensions-i-cant-live-without/">
emacs extensions i can’t live without</a> (2009)</li>
</ul>
<p>Screencasts:</p>
<ul>
<li><a href="http://platypope.org/yada/emacs-demo/">I need a cool European accent</a></li>
<li><a href="http://www.vimeo.com/1013263">What You Can Learn From ido.el</a></li>
<li><a href="http://www.youtube.com/watch?v=76Ygeg9miao#t=01m47s">YASnippet demo</a></li>
</ul>
<p>Install method:
<del><a href="http://www.saltycrane.com/blog/2008/10/installing-emacs-23-cvs-ubuntu-hardy/">
from source</a></del>
<code>sudo apt-get install emacs</code>
</p>
<p>Useful packages:</p>
<ul>
<li><a href="http://www.gnu.org/software/tramp/">
Tramp</a>: transparent remote file access</li>
<li><a href="http://www.emacswiki.org/emacs/InteractivelyDoThings">
ido</a>: Buffer switching and more</li>
<li><a href="http://orgmode.org/">Org-Mode</a>: note taking, task lists</li>
<li><a href="http://github.com/yoshiki/yaml-mode">yaml-mode</a>: for yaml</li>
<li><a href="http://jblevins.org/projects/markdown-mode/">markdown-mode</a>: for markdown</li>
<li><a href="http://code.google.com/p/yasnippet/">YASnippet</a>:
Textmate-inspired templating. Great for making HTML less tedious.</li>
<li><a href="https://github.com/nonsequitur/smex">smex: IDO for M-x</a></li>
<li><a href="https://github.com/magnars/multiple-cursors.el">multiple-cursors</a>: this is really fun *and* useful.</li>
<li><a href="http://web-mode.org/">web-mode</a>: for HTML/CSS/Javascript</li>
</ul>
<p>My emacs config on github: <a href="http://github.com/saltycrane/emacs">http://github.com/saltycrane/emacs</a></p>
<p>History: 2001: Emacs/NEdit/UltraEdit, 2006: Eclipse, 2007: Emacs</p>
</td>
</tr>
<tr>
<td id="terminal"><p>Terminal</p>
<a href="#terminal" title="Section permalink" class="sectionlink">¶</a></td>
<td><p><a href="http://software.schmorp.de/pkg/rxvt-unicode.html">urxvt</a></p>
9.19
+ <br><a href="http://www.gnu.org/software/screen/">screen</a></td>
<td>
<p>urxvt supports xft (anti-aliased) fonts, real transparency (not that
I actually use transparency with Qtile), and fading (which I do use with Qtile)
and it is much faster and lighter than gnome-terminal or konsole. screen allows me to switch
terminal sessions without ugly tabs, attach to remote sessions, search through
the scrollback buffer, and more. <em>Update:</em> urxvt also has embedded perl.</p>
<p>Install method:
<del><a href="/blog/2009/11/how-make-urxvt-look-gnome-terminal/">from source</a></del>
<code>sudo apt-get install rxvt-unicode</code>
</p>
</td>
</tr>
<tr>
<td id="vcs"><p>Version Control System</p>
<a href="#vcs" title="Section permalink" class="sectionlink">¶</a></td>
<td>
<p><a href="http://git-scm.com/">Git</a></p>
</td>
<td>
<p>Switched from Subversion to Mercurial in June 2007. The merging in Mercurial
is very nice and can be done without thinking. I do miss Subversion/Subclipse's
revision history viewer, file compare, and ability to isolate files apart from
changesets. <em>Update 2010-04-05:</em> See <a href="#c8633">my comment
below</a>.
</p>
<p><em>Update 2011-05:</em> Switched my personal repos to Git. Use Git almost
exclusively now.
</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://jonchu.posterous.com/16445171">
DVCS: Why I chose Mercurial over Git</a> (2010)</li>
<li><a href="http://blog.extracheese.org/2010/05/why-i-switched-to-git-from-mercurial.html">
Why I Switched to Git From Mercurial</a> (2010)</li>
</ul>
<p>Install method: <code>sudo apt-get install mercurial</code></p>
<p>History: 2001: SCCS, 2003: Other, 2007: Subversion, 2007: Mercurial,
2010: Mercurial/Git, 2011: Git</p>
</td>
</tr>
<tr>
<td id="high-level-language"><p>"High-level" Language</p>
<a href="#high-level-language" title="Section permalink" class="sectionlink">¶</a></td>
<td><p>None</p></td>
<td>
<p>Previously, I used C. Now I use don't use any statically-typed languague. Wouldn't mind learning <del>C++</del> Go. Although,
Linus <a href="http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918">
doesn't like it.</a></p>
</td>
</tr>
<tr>
<td id="high-high-level-language" ><p>"High-high-level" Language</p>
<a href="#high-high-level-language" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://www.python.org/">Python</a> 2.7</p></td>
<td >
<p>My love for Python is strong. I switched from Perl in 2005
and have no regrets. Object-oriented, easy to read (no more
<a href="http://en.wikipedia.org/wiki/There_is_more_than_one_way_to_do_it">
TIMTOWTDI</a>), and smart people use it. I also want to learn Javascript 2
becuase it is the
<a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html">
"Next Big Language"</a> and Lisp because it is the
<a href="http://www.paulgraham.com/avg.html">"most powerful language"</a>.</p>
<p><b>On Python vs. Ruby:</b> from what I've read, I characterize Ruby as the
more expressive language more similar to Perl (than Python is) and Python
as the more regimented language. Since I like regimented, I like Python.</p>
<p><b>On Python vs. Lisp:</b> I've concluded that I lack the intelligence to
harness enough of Lisp's power to counteract its non-practicality (e.g.
lack of libraries).</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Paul_Graham">Paul Graham</a>:
<a href="http://www.paulgraham.com/icad.html">Python is
getting closer to Lisp</a> (2002)</li>
<li>Paul Prescod: <a href="http://www.prescod.net/python/IsPythonLisp.html">
no it isn't</a></li>
<li>Paraphrase of <a href="http://www.swiss.ai.mit.edu/~gjs/">
Gerald Jay Sussman</a> (one of the creators of Scheme):
<a href="http://blog.snowtide.com/2009/03/24/why-mit-now-uses-python-instead-of-scheme-for-its-undergraduate-cs-program">
Why MIT now uses python instead of scheme for its undergraduate CS program</a>
(2009)</li>
</ul>
<p>Install method: preinstalled on Ubuntu</p>
<p>History: 2001: <a href="http://www.perl.org/">Perl</a>,
2005: <a href="http://www.python.org/">Python</a>
</p>
</td>
</tr>
<tr>
<td id="web-framework" ><p>Web Framework</p>
<a href="#web-framework" title="Section permalink" class="sectionlink">¶</a></td>
<td >
<p>
<a href="http://www.djangoproject.com/">Django</a> /
<a href="http://flask.pocoo.org/">Flask</a>
</p>
</td>
<td >
<p><em>2014-10:</em>I now use Flask at work. Previously, I used Django. I think I like SQLAlchemy and Jinja2 better than Django. Django has a lot more built in and is put together better. Flask's thread locals are convenient and messy. Probably <a href="http://www.pylonsproject.org/">Pyramid</a> is the best but no one uses it.</p>
<p>Here are some links:</p>
<ul>
<li><a href="http://www.ianbicking.org/">Ian Bicking</a>:
<a href="http://blog.ianbicking.org/theres-so-much-more-than-rails.html">
There's so much more than Rails</a> (2005)</li>
<li><a href="http://blog.ianbicking.org/2008/01/12/what-php-deployment-gets-right/">
What PHP deployment gets right</a> (2008)</li>
<li><a href="http://www.feedmagnet.com/blog/django-vs-rails/">
Django vs. Rails</a> (2009)</li>
</ul>
<p>Install method: <code>pip install Django</code> / <code>pip install Flask</code></p>
</td>
</tr>
<tr>
<td id="web-browser"><p>Web Browser</p>
<a href="#web-browser" title="Section permalink" class="sectionlink">¶</a></td>
<td><p>Firefox</p></td>
<td >
<p>Not to be confused with <a href="http://www.konqueror.org">
Konqueror</a>, Conkeror is an emacs-like, keyboard driven, scriptable,
Mozilla-based web browser. I've used it almost full
time since January 2008. It is still considered alpha stage software
so there are a number of bugs. However, it is still pretty sweet. I use
Firefox as a backup (and IE Tab for Launchcast and Netflix on Windows).</p>
<p>Unfortunately, one of the annoying things in Firefox 2 is present in
Conkeror as well-- memory leaks. Based on
<a href="http://kb.mozillazine.org/Memory_Leak">this Mozilla article</a>
and some brief personal experience, Firefox 3 has made fixes in this area.
It would be nice if Conkeror could benefit from the Firefox 3 fixes.</p>
<p><em>Update 2010-05-04:</em> Conkeror is really awesome, but I had some memory/cpu issues with it
a while ago and haven't put in the work to merge my custom keybindings
with the latest Conkeror code. Also waiting to see if there will be
an Emacs version of <a href="http://vimium.github.com/">Vimium</a>
(since, after all <a href="http://vimperator.org/">vimperator</a>
followed conkeror).
</p>
<p>I'm currently using a combination of Google Chrome and Firefox.
Chrome is faster, especially for Javascript-intensive sites, but I really
<a href="http://superuser.com/questions/91334/alternative-to-arrow-keys-in-google-chrome-location-bar">
<em>hate</em> the Google Chrome Omnibar</a>. If you have a solution
or workaround, please post an answer. Firefox also has some Add-ons
that Chrome doesn't.
</td>
</tr>
<tr>
<td id="email" ><p>Email</p>
<a href="#email" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p>Gmail</p></td>
<td >
<p><em>Update 2010-05-04:</em>
Gmail. It's slow but it has a lot of features and it's in
my web browser and it's easy and it works and I don't really like using
email that much anyways. Oh, and, big plus, syncing works almost perfect
with my Android phone. (Actual full switch to Gmail was around December 2008.)
</p>
</td>
</tr>
<tr>
<td id="graphical-diff" ><p>Graphical diff/merge</p>
<a href="#graphical-diff" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://kdiff3.sourceforge.net/">KDiff3</a></p></td>
<td >
<p>I started using KDiff a while ago on Windows and have
always liked it. I'm thinking, though, since I'm an Emacs person, I ought to
use <a href="http://www.gnu.org/software/emacs/manual/html_mono/ediff.html">
Ediff</a>.</p>
<p>Install method: <code>sudo apt-get install kdiff3</code></p>
</td>
</tr>
<tr>
<td id="keyboard"><p>Keyboard</p>
<a href="#keyboard" title="Section permalink" class="sectionlink">¶</a></td>
<td>
<p><a href="http://pckeyboards.stores.yahoo.net//en104wh.html">
Unicomp Endurapro</a> /
<a href="http://elitekeyboards.com/products.php?sub=leopold,tenkeyless&pid=fc200rtab">
Leopold Tenkeyless w/ Cherry MX Browns
</a></p>
</td>
<td>
<p>I realize a keyboard is hardware and not software, but it is
hardware that can evoke strong opinions, so I made an exception.
</p>
<p>One problem with hardware is I can't try out all the different types
and choose the one I like the best as I can with software. So
my selection is based on reviews not on actual experience. And,
after buying the Endurapro, I found I actually did not like the
integrated mouse stick, so I should have bought a Customizer 104/105
and saved $30.</p>
<p><em>Update 2011-05:</em> Got the Leopold tenkeyless for work.
Tenkeyless is a must for quicker mouse access.
And I actually like the lighter touch of the
Cherry MX Browns versus the Unicomp's buckling springs. I like it
so much I want to replace my Unicomp at home with another Leopold.
</p>
<p><em>Update:</em> Got a second Leopold for home to replace my Unicomp.</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://www.jwz.org/gruntle/wrists.html">
my wrists and welcome to them.</a>, JWZ (1999)</li>
<li><a href="http://www.dansdata.com/deck.htm">
Deck keyboard</a>, Dan (2005)</li>
<li><a href="http://bc.tech.coop/blog/060131.html">
Surviving Emacs - Part 4</a>, Bill Clementson (2006)</li>
<li><a href="http://glyf.livejournal.com/55780.html">
Keyboard Fight</a>, Glyph Lefkowitz (2006)</li>
<li><a href="http://diveintomark.org/archives/2006/05/30/bye-apple">
Bye, Apple</a>, Mark Pilgrim (2006)</li>
<li><a href="http://glyph.twistedmatrix.com/2009/01/meandering-review-of-logitech.html">
A Meandering Review of the Logitech Illuminated Keyboard</a>,
Glyph Lefkowitz (2009)</li>
</ul>
<p>History: 2009: Unicomp Endurapro, 2011: Leopold Tenkeyless (MX Browns)</p>
</td>
</tr>
<tr>
<td id="office-chair"><p>Office Chair</p>
<a href="#office-chair" title="Section permalink" class="sectionlink">¶</a></td>
<td><p>Undecided</p></td>
<td><p>Herman Miller Aeron or Steelcase Leap</p>
</td>
</tr>
<tr>
<td id="mobile-phone"><p>Mobile Phone</p>
<a href="#mobile-phone" title="Section permalink" class="sectionlink">¶</a></td>
<td><p><a href="http://www.motorola.com/Consumers/US-EN/Consumer-Product-and-Services/Mobile-Phones/Motorola-DROID-US-EN">Motorola Droid 4</a></p></td>
<td>
<p>After almost 10 years (and 3 generations) of the Palm Treo, I got the
Motorola Droid.</p>
<p>The Droid is pretty awesome, but I don't like switching
to landscape mode to use the keyboard-- especially when toolbars and headers
take up half the screen. I think Palm and Blackberry got this form factor Right.
Just as I prefer the keyboard over the mouse on my PC, I want to use the keyboard
and D-pad over the touchscreen on my phone.
<em>Update 2010-05-04:</em> The keyboard is mediocre and use of the D-pad
center button sucks. My Palm Treo 650 D-pad worked much better.
</p>
<p>My reasons for choosing an
<a href="http://en.wikipedia.org/wiki/Android_%28operating_system%29">Android</a>
phone are: I <em>need</em> a physical keyboard.
I <em>want</em> to hack on my phone. I <em>think</em> Android has more potential than Palm's
<a href="http://en.wikipedia.org/wiki/WebOS">webOS</a>
or <a href="http://en.wikipedia.org/wiki/Maemo">Maemo</a>.</p>
<p>Useful apps:</p>
<ul>
<li><a href="http://code.google.com/p/connectbot/">Connectbot</a>
Secure shell (SSH) client for the Android platform. Use this all the time. Awesome.</li>
<li><a href="http://www.android.com/market/#app=listen">Listen</a>
Listen from Google Labs brings podcast search, subscribe, download and stream to your Android-powered device.</li>
<li><a href="http://mytracks.appspot.com/">My Tracks</a>
Record GPS tracks. Monitor your performance. Share your outdoor activities with friends.
Really enjoy this one. Love tracking my romping.
</li>
</ul>
<p><em>2010-05-04 Updates:</em></p>
<ul>
<li><a href="http://www.google.com/mobile/voice/">Google Voice</a>: Free text messages
and better voicemail. Another useful app. Makes voicemail suck a lot less.</li>
<li><a href="http://levelupstudio.com/foxyring">FoxyRing</a>: automatically
control the ringer volume based on ambient noise level. I was doubtful about this one,
but it actually works well for me.</li>
<li><a href="http://www.flixster.com/mobile/apps/android">Flixter (Movies)</a>:
Useful for checking movie showtimes.
</li>
<li><a href="http://www.youversion.com/mobile/android">Bible (YouVersion)</a>:
This version is pretty good. I miss my <a href="http://www.plkr.org/">Plucker</a>
created Bible on my Palm though. I wish there was something like Plucker for
Android.
</li>
<li>DroidLight: use the LED camera flash as a flashlight. Simple and useful.
Works much better than using the screen as a flashlight.
</li>
<li><a href="http://www.google.com/mobile/navigation/">Google Navigation</a>: I
don't need my Garmin anymore. (Each has advantages and disadvantages, but I
have found it to be a capable replacement.)</li>
<li>Just want to mention that the Calendar sucks. It is great that I can sync
with my Google calendar, but I really hate the Android Calendar UI.</li>
</ul>
<p>Additional Commentary/Links:</p>
<ul>
<li><a href="http://randomfoo.net/2009/06/15/thoughts-on-the-palm-pre-g2-and-iphone-3g">
Thoughts on the Palm Pre, G2, and iPhone 3G</a> Leonard Lin (2009 June)</li>
<li><a href="http://jwz.livejournal.com/1055120.html">
JWZ gets a Palm Pre</a> (2009 June)</li>
<li><a href="http://jwz.livejournal.com/1055369.html">
Emacs on Android</a> (2009 June)</li>
<li><a href="http://daringfireball.net/2009/08/the_android_opportunity">
The Android Opportunity</a>, John Gruber (2009 August)</li>
<li><a href="http://jwz.livejournal.com/1108212.html">
Dear Palm, it's just not working out</a>, JWZ (2009 October)</li>
</ul>
<p>History: 2002: <a href="http://en.wikipedia.org/wiki/Treo_180">Handspring Treo 180</a>,
2003: <a href="http://en.wikipedia.org/wiki/Treo_600">Handspring Treo 600</a>,
2005: <a href="http://en.wikipedia.org/wiki/Treo_650">Palm Treo 650</a>,
2009: <a href="http://en.wikipedia.org/wiki/Motorola_Droid">Motorola Droid</a>
2011: <a href="http://en.wikipedia.org/wiki/Droid_4">Motorola Droid 4</a>
</p>
</td>
</tr>
</table>