Switching SVN branches using Git

Git and I normally have this fabulous relationship where Git does whatever I tell it to do and I am completely in love with the fact that it actually works. However, Git and I are having one of those trying times in our relationship where I want it to do something that seems complete impossible… and while Git does come with instructions, they are not very good if you want to do something hard or weird.

Here is the short version of the story: I am working on a project that is using a remote SVN repository. I have been using Git-SVN, since there have been (a few too many) times where I need to work on several tasks at once and not be able to commit anything immediately. So:

      > git branch foo
      > git checkout foo
      [hack.. hack... hack...]
      > git commit 
      [days go by]
      > git svn dcommit

Easy enough, right?  This has been working wonderfully for weeks; however all of a sudden:

      > git branch bar
      > git checkout bar
      [hack.. hack... hack...]
      > git commit
      [days go by]
      [oh.. by the way, can you commit your changes to this other branch instead?]

Crap.  I now have several commits in my new branch that have been committed to Git, but now need to be committed to a different SVN branch.  Now I need to find a way to do my svn switch in Git.

One would think there would be a simple command for this.  But… um… no.  Now, there are a number of forum and blog posts that pop up on the topic if you do a Google search for git svn switch.  Most of those results did not work for me at all; however I did find one post from www.beletsky.net that helped tremendously.  The first part of the solution to my problem is snipped from that post (with my own annotations to help figure out what is going on here).

1. Modify your Git config file.

Mine was in .git/config, but I understand that they could all be in different locations.  You probably have something in there already that looks like this:

      [svn-remote "svn"]
         url = [OLD-REPO]
         fetch = :refs/remotes/git-svn

You will need to add an additional entry in the config file that reads:

      [svn-remote "svnnew"]
         url = [NEW-REPO]
         fetch = :refs/remotes/git-svn-new

2. Fetch your changes from the new SVN repository.

Just a note: this will take a very long time, depending on the size of your SVN repository.  Go grab a coffee or something after firing this off.

      > git svn fetch svnnew

3. Checkout your new SVN repository in Git.

This puts you into something called “detached HEAD” state.  I’m not entirely sure what that means, but it basically allows you to create a new base branch in Git for your new SVN repository.

      > git checkout git-svn-new

4. Create your new Git branch.

This will create a new Git branch that will now be associated with your new SVN repository.

      > git checkout -b master-new

5. Look up the commit(s) from your old branch.

You will need the commit IDs from your old branch, for use when you merge the changes into your new branch.

      > git checkout old-branch
      > git log --pretty=oneline

You should get output something like the output below.  This is the commit ID followed by the commit message you entered when you did your git commit.  Note that the most recent commit is at the top of the list.  Jot down all of the commits you want to move over to your new branch.

      f8dace1a7b96ee59a6b5237920eb18da49fed0bf Commit #3
      e2a93ad2f20621c33625cbc37f7a3818236ad761 Commit #2
      6f72923317778e32fd67495c3599b825ead05f10 Commit #1

6. Cherry pick your commits.

You can use the git cherry-pick command to move your commits (one by one) from your old branch to your new branch.  Use the commit ID that you grabbed from the step above.  If you need to move over more than one commit, you will need to cherry pick each commit individually, starting with the commit that was committed first.  The example below moves over commits #2 and #3 from the list above.  Notice which commit ID I use first.

      > git checkout master-new
      > git cherry-pick e2a93ad2f20621c33625cbc37f7a3818236ad761
      > git cherry-pick f8dace1a7b96ee59a6b5237920eb18da49fed0bf

It is entirely possible that you will have code conflicts as you cherry pick your commits, which is one of the reasons why you should do each commit separately.  Git will let you know if there is a conflict.  (Here is more information on cherry picking and conflicts.)

Voila!

Once you are done, there are a couple of commands you can run to verify everything is correct:

      > git svn info  # gives you information on what SVN branch you are synced to
      > git log       # gives all commits in your Git branch; use to confirm your are in the new branch

Goodbye 2011… Hello 2012!

It amazes me that yet another year has come and gone.  The year 2011 was quite the year, full of craziness and joy (if those two adjectives can go together).

This year marked my second year working at Optaros, where I have been learning everything from YUI (2 and 3), to Drupal (6 and 7), to even a little bit of Magento towards the end.  I had never really traveled for this job before, but the end of the year took me on a whirlwind tour of San Francisco (my first time!), then Austin, then Troy NY, and then back to Austin, all within the span of 6 weeks.  Absolute insanity, but also exciting!

In more exciting news, I was lucky enough to go on not one, but two cruises this past year!  Last February, I went on my first Ships and Dip cruise, which is basically a giant music festival on a boat in the Caribbean.  I saw more Barenaked Ladies and Great Big Sea shows that week than I had in probably the last 10 years.  I also met a bunch of great new friends – who new that letting people cut in front of you in line would be great?!   In November, I went on my second Eddie From Ohio cruise.   This was definitely one of the high points of my year – I love this band!   I got to see old friends I rarely see, and made many new ones.  I even got to sing with the band!

Speaking of high points, one of my goals for 2011 was to run my first 10k race… and I completely crushed that goal.  I ran my first half marathon this past October (in 2:17:52) and, with the help of my friends and family, raised $1535 for Dana Farber in the process!

In other news, I have been blogging and reading and coding quite a bit this year.  I did move over the summer, not quite as far as I thought I would have, but I discovered that uprooting myself for no good reason other than the fact that I am still at a point in my life where I can just is not quite good enough now as it was 8 years ago.

All of this brings me to 2012.  Everyone makes new year’s resolutions, and I know I am no different, but I also recently read that it is much better to make 3 really solid resolutions as opposed to many more, smaller ones.  I am not so sure about that, but I will do my best!  Here are my 5 resolutions for this coming year:

  1. Keep running and finish my 2nd half marathon by the fall.  This is really just part of my general “take better care of myself” goal, but I like to have something specific to work towards.
  2. Travel – and I do not mean just for work.  I would love to go overseas again.  I have a couple of destinations in mind already.  (Yes, Lebanon is one of them, as long as the stars align and all the shenanigans in that part of the world do not spill over the border.)
  3. Work on more independent coding projects.  I would like to have at least 2 under my belt by the end of this year.
  4. Be bold.  Ok, this one is not exactly specific, but they can’t all be, right?
  5. Read more.  I made it to 32 books last year; perhaps I will beat that number this year.

Here is hoping these all come true.  Happy 2012!  May this year be the best year ever!

Cheap Trick with YUI Carousel

This is just another example of why Internet Explorer 7 (and earlier) needs to die. I have been working on a project where a group of images needs to be displayed on a page, four at a time in a carousel. The site uses YUI 2.7, so naturally, I am using YUI Carousel to implement this.

In addition to displaying the images, the end user has the option to select one of these images to be selected as a primary image by clicking on that image. When the user selects a new primary image, a banner is displayed across the bottom of the image indicating its “primary” status. So, I added an event listener to add a div to the image’s container whenever said image is clicked. Simple enough, right?

Nope. Firefox was fine, but I came across an issue in IE where the carousel “jumped” so that my newly selected primary image displayed as the first image in the carousel and all other images ahead of it disappeared.

Long story short, clicking on an element in a YUI carousel causes that element to be selected. Selecting an element in a YUI Carousel in IE (apparently) forces that element to be displayed first.

The fix? A hack!  Basically, the YUI Carousel comes with a “beforeSelectedItemChange” event, on which if you return false, the default behavior is negated.  This works for both Firefox and IE.

    changePrimary = true;
    imageCarousel.on("beforeSelectedItemChange", function() {
        if (changePrimary) {
            changePrimary = false;
            return false;
        }
    });

Link Post #4 – UX articles

In my (online) travels, I tend to come across a lot of articles that are centered around design and user experience.   There are so many that, to be perfectly honest, they get lost in my bookmarks.  So, instead of hiding them away in a list inside my browser that I will probably never see again (since Firefox did a really good job at hiding my bookmark list), I am opting to post them here and share them with the rest of the world (or, at the very least, those of you who read this blog).

  • New research on “The Psychology of Sharing”
    Speaking of sharing, this is a very interesting article about why people share content online.

  • The Experience of the Thing
    Another interesting article, written by a friend of mine, about UX and the power of a positive brand experience.

  • Dyslexie, A Typeface Designed to Help Dyslexics Read
    This is just fantastic!  The article describes the science behind new typeface and how it was developed.

  • Mac/PC
    Ok, this is not an article.  But this comic hits the nail on the head.  Our digital world is practically completely online.  It is an easy argument to make that what operating system we use is now moot.

  • Git: A Designer’s Primer
    I have jumped on the Git bandwagon and I think you should too.  Git is just great.  There is a learning curve, but once you are over that hump, it is a lightweight and relatively simple system to use.  Plus, it sits nicely on top of SVN.

Adding a character limit to a text area (YUI)

In the UI world, it is a good idea to let the users know about any constraints they have on any form fields.  We all know this.  There are a million ways to do this – through error messages, help text, and so on.  For character limits on input fields, the best way to avoid a user error is to limit the number of characters the user can physically type in the field.

This is super easy for input boxes.  Simply add the maxlength attribute to the input HTML filed and voila!

However, text area fields are a bit trickier.  Character limits are not built into text area fields just yet as they are with input fields, so it is necessary to have a Javascript implementation if you need to limit the text prior to submitting a form.

So… I decided to write one.  I sort of ran away with this example, mostly because there are so many things to consider from a user perspective.  If someone is entering in a longer piece of text – for example, an e-mail to a customer service department or a review on a product – is it really better to just cut them off from entering more text before they have finished their thought?  True, the user will not be able to submit the form until their giant essay has been tamed to fit within the character constraints.  From a programmatic perspective, it is better to simply cut the user off.  This ensures a successful form submission.

On the other hand, there are some people (like me) who would much rather finish their thought, and then go back and edit the text down to size.  In this case, it is much more useful to have an (obvious) indicator of how long the entered text is, so that the user knows how much needs to be cut.

Long story short (I know… too late), I decided to create a proof of concept for limiting character limits that contains options for both scenarios above.


Step 1: Create a web page.

First, I created a very simple page with 3 elements:

  1. A text area input field.
  2. A message letting the user know how many characters they have typed and how many characters they are allowed.
  3. A check box to determine whether or not the text box will allow the user to continue to enter text once they have reached the character limit.

Step 2: Write the Javascript.

The Javascript part of this POC contains 3 major functions:

1. Function to update the text area alert

This function is called as soon as the page loads and then each time a key is pressed (on the keyup event) to update the number of characters used in the character limit message to the user.  Also, if the user has entered more characters than allowed by the limit, the truncate text area function is called.

  function updateTextAreaAlert() {
    var text = Dom.get("yui-textarea").value;
    var charsUsed = text.length || 0;

    if (charsUsed >= textLimit) {
      Dom.addClass("yui-textarea-chars", "over-limit");
      truncateTextArea();
    }

    else if (charsUsed >= textLimit * 0.9) {
      Dom.addClass("yui-textarea-chars", "near-limit");
    }

    else {
      Dom.removeClass("yui-textarea-chars", "near-limit");
      Dom.removeClass("yui-textarea-chars", "over-limit");
    }

    Dom.get("yui-textarea-chars").innerHTML = charsUsed;
  }

2. Function to check the text area limit.

This function checks to see if the value of the text area field is longer than the set character limit.  If so, the function to truncate the text area’s contents is called.  This function is called each time a key is pressed on the key down event.  This is to avoid issues with the text “jumping” – the text area contents are actually updated after the key down event is called – so we call this function on key down so that we have a chance to suppress the content update if the user is over the character limit.

  function checkTextAreaLimit(e) {
    var text = Dom.get("yui-textarea").value;

    // Check to see if a delete key was pressed; backspace is 8; delete is 46.
    var key = (window.event) ? e.which: e.keyCode;
    var pressedDel = (key == 8 || key == 46) ? true : false;

    if (!allowOverLimit() && text.length >= textLimit && !pressedDel) {
      Event.preventDefault(e);
      truncateTextArea();
    }
  }

3. Function to truncate the contents of the text area.

This function truncates the text in the text area field if the user is over the character limit.  This function is called by the two functions listed above.

  function truncateTextArea() {
    var text = Dom.get("yui-textarea").value;

    if (!allowOverLimit()) {
        Dom.get("yui-textarea").value = Dom.get("yui-textarea").value.substring(0, textLimit);
        Dom.get("yui-textarea-chars").innerHTML = Dom.get("yui-textarea").value.length;
    }
  } 

You can check out the completed proof of concept at: http://examples.jhalabi.com/textarea-limit/.

Follow

Get every new post delivered to your Inbox.