Why I’m ditching Mercurial in favour of Git

When I first decided I wanted to use a DVCS to manage the source code of my various projects, I was initially sold on using Mercurial by Joel Spolsky’s excellent HG Init tutorial (which is a great intro DVCSs in general by the way – highly recommended).

As a result, for the last year or so I’ve been using Mercurial day-in-day-out. It’s a great tool and I would still recommend it.

However, over the last few months, as I’ve been forced to use Git more and more (primarily due to GitHub’s status as the VCS provider du jour for open source projects). As a result I’ve come to realize that, despite it’s arguably slightly more complex command interface, Git fits my needs better than Mercurial.

Here are the top 5 reasons why:

1. Automatic support for renaming/moving files

If, like me, you tend to rename class files numerous times when attempting to settle on the name that works best, you might find file renaming a bit of pain in Mercurial. By default, Mercurial handles a rename as a Remove of the original filename and an Add of the renamed filename. This is a little suboptimal as it means by default we lose the file history at the point we rename the file.

To ensure the history is preserved, Mercurial allows you to let it know about rename operation, either by performing the rename using Mercurial itself…

hg rename oldfilename newfilename

…or by telling it about a rename you’ve already performed…

hg rename --after oldfilename newfilename

But this is kind of a pain. If you’re working with an IDE such as Eclipse, you’ll want to do your renaming in the IDE to take advantage of its ability to automatically update references. If you decide to rename a number of files this way you’re faced with needing to tell Mercurial about each one individually.

Moreover, consider moving a folder containing a large number of files. Again, a file move is treated just like a rename in Mercurial – as a Remove and an Add. If you decide to reorganise your repo’s folder structure using an IDE you’re potentially faced with needing to tell Mercurial about a ton of renames.

Contrast this with Git. Git tracks the contents of files rather than filenames. As a result it detects is able to handle file renames or moves automatically by simply comparing the contents of the original file and renamed file. No further user action is required.

I’ve found this to be a massive time saver when working with Java projects in Eclipse where it’s common to want to refactor a package structure resulting in a lot of moved files.

2. Heroku integration

Heroku is awesome. I use Heroku a lot to deploy my Rails and Node.js apps. I find that as an application platform it provides just the right level of abstraction allowing you to run your own code, with your own dependencies inside your own web server, without having to deal with any of the complexity associated with provisioning the infrastructure itself.

In order to deploy your code to Heroku you need to use Git. You simply add your Heroku app instance as a Git remote and push to it. Heroku takes care of the rest.

Clearly, if you’re going to use Git to deploy code to Heroku, it makes sense to use Git to manage your code as well.

3. The Git Index

The Git Index is essentially the staging area to which you must add any file changes you want to commit prior to actually committing them. By default, if you simply make changes to files in your working copy of a Git repo, those changes will not be committed if you issue a git commit command. First you must add to the index the file changes you want to include in the commit using git add.

At first this might seem like additional work and/or complexity, but it is actually incredibly useful. I frequently find myself making a bunch of changes together which logically serve different purposes. e.g. I notice a spelling mistake in some file unrelated to the changes I’m making and correct it while I’m in the neighbourhood. In this scenario, the Git Index allows me to create two separate commits from set of changes I’ve made: one for the spelling mistake correction, and another for the actual changes I planned to make.

Contrast this with Mercurial. Although internally it uses an index, Mercurial does not expose this to the user. By default all changes to a working copy are included in a commit (though new files must be explicitly added). If you want to include only a subset of your changes in a given commit, you must list the files you want to include at the point you  make the commit.

Mercurial

hgdemo tom$ hg st
M a.txt
M b.txt
hgdemo tom$ hg commit -m "Committing a.txt" a.txt
hgdemo tom$ hg st
M b.txt

Git

gitdemo tom$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#	modified:   a.txt
#	modified:   b.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
gitdemo tom$ git add a.txt 
gitdemo tom$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#	modified:   a.txt
#
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#	modified:   b.txt
#
gitdemo tom$ git commit -m "Committing a.txt"
[master 980c086] Committing a.txt
 1 files changed, 1 insertions(+), 0 deletions(-)

This may seem like a small functional difference, but the ability to iteratively add files to and review the Git Index prior to actually committing means you have a lot more confidence that what you are committing is actually correct.

Furthermore it encourages good behaviour. With Mercurial it is very easy to get into the habit of just committing everything together because it’s the path of least resistance. Git forces you to think about what you’re committing which gives you a better chance of structuring your commits more logically so they can be cherry-picked for merging more easily later on.

4. Better colour highlighting of file status and diffs

Out of the box, Git does a great job of using colour highlighting to indicate which files are currently in the index, which are not and how file contents have changed when doing a diff.

Though its possible to install an extension to enable this behaviour in Mercurial, I am lazy and don’t really feel like I should have to🙂.

5. It’s more widely used

Ultimately, I’ve yet to encounter an open source project I want to hack on which is managed using a Mercurial repo. Both on Google Code and Github, Git is the platform of choice. As such, Git appears to be well established the de facto DVCS of choice among the OSS community.

Sorry Mercurial. I’ll be using the HG-Git plugin to migrate all my code to Git.

Creating a reusable “fading reflection” view effect in Android

Recently I needed to create various Android UIs which provides a “fading reflection” effect for certain screen elements. I happened upon Neil Davies excellent post on creating reflections of images in an Activity in order to re-create something similar to Apple’s coverflow effect, and it set me thinking about what could be achieved using this technique.

Apple's Coverflow

Apple’s “Coverflow” provides a nice reflection effect

Really what I wanted was a way to take the approach outlined by Neil and easily apply it to potentially any View or collection of Views in a given UI without needing to write the same boilerplate in the Activity every time.

For example, lets say I have a basic layout for showing progress to which I want to add a “reflection” effect:

Without

Original

Original with added reflection

Original with added reflection

You can see that there are a couple of View objects in there (a ProgressBar and a TextView) which we’d like to apply the reflection effect to, rather than a simple image. Moreover, it would be nice to be able to add/remove UI elements at runtime and have them included in the effect as required.

Introducing ReflectingLayout

ReflectingLayout diagram

To implement this reusable reflection effect, I created a new custom View based on LinearLayout named “ReflectingLayout”. ReflectingLayout will simply apply a reflection effect to child views declared within it using the remaining space not used below those child views.

As the diagram to the right illustrates, the idea is that the layout params of the ReflectingLayout and the contained views are such that an empty region is left within the ReflectingLayout below the child views which can be used to draw a reflection. You can see that if the ReflectingLayout’s height is reduced, the area available for the reflection is also reduced.

This approach allows you to potentially insert any combination of child views, and provided you’ve allowed enough space below them within the ReflectedLayout container, you can achieve a reflection effect on anything.

The Code

As well as working through the approach here, I’ve made the source of ReflectingLayout available on GitHub if you want to reuse it, make improvements etc.

This is the declaration of ReflectingLayout:


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.widget.LinearLayout;

/**
 * A general purpose Layout which simply renders a reflection of its contained
 * child Views in the remaining space below them within the bounds of this control.
 * For {@link ReflectingLayout} to work properly, it must be setup to provide
 * sufficient empty space below its children.
 *
 * Copyright Tom
 */
public class ReflectingLayout extends LinearLayout {

  /** The maximum ratio of the height of the reflection to the source image. */
  private static final float MAX_REFLECTION_RATIO = 0.9F;

  /** The {@link Paint} object we'll use to create the reflection. */
  private Paint paint;

  private Matrix vFlipMatrix;

  /**
   * Instantiates a new reflecting layout.
   *
   * @param context the context
   * @param attrs the attrs
   */
  public ReflectingLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  /**
   * Instantiates a new reflecting layout.
   *
   * @param context the context
   */
  public ReflectingLayout(Context context) {
    super(context);
    init();
  }

  /**
   * Initialises the layout.
   */
  private void init() {
    // Ensures that we redraw when our children are redrawn.
    setAddStatesFromChildren(true);

    // Important to ensure onDraw gets called.
    setWillNotDraw(false);
    setDrawingCacheEnabled(true);

    // Create the paint object which we'll use to create the reflection gradient
    paint = new Paint();
    paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

    // Create a matrix which can flip images vertically
    vFlipMatrix = new Matrix();
    vFlipMatrix.preScale(1, -1);
  }

  /**
   * {@inheritDoc}
   * @see android.view.View#onDraw(android.graphics.Canvas)
   */
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // Only actually do anything if there is space to actually draw a reflection
    if (getReflectionHeight() > 0) {

      // Create a bitmap to hold the drawing of child views and pass this to a temp canvas
      Bitmap sourceBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
          Bitmap.Config.ARGB_8888);
      Canvas tempCanvas = new Canvas(sourceBitmap);

      // Draw the content of this layout onto our temporary canvas.
      super.dispatchDraw(tempCanvas);

      // Calculate the height of the reflection and the bottom position of child views.
      int reflectionHeight = getReflectionHeight();
      int childBottom = getMaxChildBottom();

      // Create a new bitmap from the source image which has been vertically flipped and
      // only includes the region occupied child views.
      Bitmap flippedBitmap = Bitmap.createBitmap(
          sourceBitmap,
          0,
          0,
          sourceBitmap.getWidth(),
          childBottom,
          vFlipMatrix,
          false);

      // Create a bitmap to hold just the reflection
      Bitmap fadedBitmap = Bitmap.createBitmap(
          getMeasuredWidth(), reflectionHeight, Bitmap.Config.ARGB_8888);

      Canvas fadeCanvas = new Canvas(fadedBitmap);
      fadeCanvas.drawBitmap(flippedBitmap, 0, 0, null);

      LinearGradient gradient = new LinearGradient(0, 0, 0, reflectionHeight,
          0x30FFFFFF, 0x00FFFFFF, TileMode.CLAMP);
      paint.setShader(gradient);

      // Now use some clever PorterDuff shading to get the fading effect.
      fadeCanvas.drawRect(0, 0, getMeasuredWidth(), reflectionHeight, paint);

      // Draw our image onto the canvas
      canvas.drawBitmap(fadedBitmap, 0, childBottom, null);

    }
  }

  /**
   * Finds the bottom of the lowest view contained by this layout.
   *
   * @return the bottom of the lowest view
   */
  private int getMaxChildBottom() {
    int maxBottom = 0;
    for (int i = 0; i < getChildCount(); i++) {       int bottom = getChildAt(i).getBottom();       if (bottom > maxBottom)
        maxBottom = bottom;
    }
    return maxBottom;
  }

  /**
   * Gets the highest top edge of all contained views.
   *
   * @return the min child top
   */
  private int getMinChildTop() {
    int minTop = Integer.MAX_VALUE;
    for (int i = 0; i < getChildCount(); i++) {
      int top = getChildAt(i).getTop();
      if (top < minTop)         minTop = top;     }     return minTop;   }   /**    * Gets the height of the space covered by all children.    *    * @return the total child height    */   private int getTotalChildHeight() {     // The max value of any child's "bottom" minus the minimum of any "top"     return getMaxChildBottom() - getMinChildTop();   }   /**    * Gets the height of the reflection to be drawn.    *     * @return the reflection height    */   private int getReflectionHeight() {     return (int) Math.min(         getMeasuredHeight() - getMaxChildBottom(),          getTotalChildHeight() * MAX_REFLECTION_RATIO);   } 

So what’s going on here? First let’s take a look at the init() method, used by both constructors to initialise the ReflectingLayout:

  /**
   * Initialises the layout.
   */
  private void init() {
    // Ensures that we redraw when our children are redrawn.
    setAddStatesFromChildren(true);

    // Important to ensure onDraw gets called.
    setWillNotDraw(false);
    setDrawingCacheEnabled(true);

    // Create the paint object which we'll use to create the reflection gradient
    paint = new Paint();
    paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

    // Create a matrix which can flip images vertically
    vFlipMatrix = new Matrix();
    vFlipMatrix.preScale(1, -1);
  }

The first three set…() calls ensure that the ReflectingLayout pays attention to its children and makes use of the drawing cache to ensure we only do a full redraw when necessary. We also create Paint and Matrix objects for use later on in onDraw(). This one-off instantiation is a good idea to ensure we don’t waste memory and do more garbage collection than necessary later on by repeatedly creating these objects in onDraw() which will be called a lot. The Paint is configured with the Porter-Duff transfer mode, this is what allows us to use a simple color gradient to vertically fade out images. The vFlipMatrix is simply configured to flip an image vertically to make it appear upside down. The onDraw() method is what the Android framework will call on a given View object when it want that View (and it’s children) to draw itself onto the given canvas. onDraw() methods tend to get called a lot in quick succession as a UI updates, so must be fast. Here’s ReflectingLayout’s implementation:

   protected void onDraw(Canvas canvas) {     super.onDraw(canvas);     // Only actually do anything if there is space to actually draw a reflection     if (getReflectionHeight() > 0) {

      // Create a bitmap to hold the drawing of child views and pass this to a temp canvas
      Bitmap sourceBitmap = Bitmap.createBitmap(
          getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
      Canvas tempCanvas = new Canvas(sourceBitmap);

      // Draw the content of this layout onto our temporary canvas.
      super.dispatchDraw(tempCanvas);

      // Calculate the height of the reflection and the bottom position of child views.
      int reflectionHeight = getReflectionHeight();
      int childBottom = getMaxChildBottom();

      // Create a new bitmap from the source image which has been vertically flipped and
      // only includes the region occupied child views.
      Bitmap flippedBitmap = Bitmap.createBitmap(
          sourceBitmap,
          0,
          0,
          sourceBitmap.getWidth(),
          childBottom,
          vFlipMatrix,
          false);

      // Create a bitmap to hold just the reflection
      Bitmap fadedBitmap = Bitmap.createBitmap(
          getMeasuredWidth(), reflectionHeight, Bitmap.Config.ARGB_8888);

      Canvas fadeCanvas = new Canvas(fadedBitmap);
      fadeCanvas.drawBitmap(flippedBitmap, 0, 0, null);

      LinearGradient gradient = new LinearGradient(0, 0, 0, reflectionHeight,
          0x30FFFFFF, 0x00FFFFFF, TileMode.CLAMP);
      paint.setShader(gradient);

      // Now use some clever PorterDuff shading to get the fading effect.
      fadeCanvas.drawRect(0, 0, getMeasuredWidth(), reflectionHeight, paint);

      // Draw our image onto the canvas
      canvas.drawBitmap(fadedBitmap, 0, childBottom, null);
    }

Hopefully the code comments are fairly self explanatory, but the general approach is as follows:

  • It’s important to call super.onDraw(canvas). This will ensure that the child views are drawn in the normal way onto the main canvas. Otherwise we’d appear to have a reflection of some non-existent objects.
  • We then get the child views to draw themselves again into a Bitmap object via a temporary Canvas we create. This then gives us a Bitmap we can manipulate to achieve the reflection effect.
  • The Bitmap is used to created a second version which has been cropped at the “childBottom” (the y position of the bottom most edge of any child View, in our case the TextView) and then flipped vertically. This then forms the basis for our reflection image.
  • We then configure our Porter-Duff-enabled Paint object with a vertical gradient covering the full height of the reflection image, so that the fading out of the reflection is correctly calibrated.
  • The Paint is then used to “draw” a rectangle over base reflection image, having the effect of fading it out.
  • Finally the resultant Bitmap is drawn onto the main canvas starting just below the bottom of the child Views.

A couple of final points

I have noticed that certain changes made at runtime to child Views of ReflectingLayout sometimes don’t result in the ReflectingLayout getting redrawn. I’m not 100% sure why this is but I believe it’s related to Android’s view optimisations trying to prevent redraws whenever possible. If Android thinks it can get away with only redrawing a given child of ReflectingLayout in response to a change to that just that view (e.g. a change of text color, rather than a change in layout) then onDraw() on ReflectingLayout does not get called and the reflection does not get updated.

This is a bit annoying. I had hoped there would be come mechanism to “hook in” to child redraw events from ReflectingLayout but have not managed to find anything. If anyone can suggest a suitable approach please let me know. For now, I have resorted to calling invalidate() on the ReflectingLayout whenever updating one of its children to ensure the reflection is refreshed.

Happy reflecting!