Tagging Stashes in Git

On many of the projects I develop, I often need to temporarily apply a particular set of changes to my working directory. For example: I may wish to apply some settings in order to run a command or perform a test.

Git’s stash feature makes this easy. First make the changes you will need to apply again. Then run git stash.

When you want to apply your stash in the future, you can retrieve your list of stashes via git stash list:

$ git stash list
stash@{0}: WIP on master: 531b57e small bug fix
stash@{1}: WIP on master: a5f035f updates
stash@{2}: WIP on master: 7bd979b copy fix

and apply it like so:

$ git stash apply stash@{1}

When you are finished with the changes, you can reset your working directory. Later, when needed, you can reapply them using the stash apply command shown above.

There are a few shortcoming with this method however:

  1. stash@{1} isn’t memorable
  2. it isn’t easy to type
  3. its number scheme is relative, e.g. if you pop the top stash, the stash@{1} reference becomes stash@{0}

And unfortunately, in case you were wondering, we can’t use the message we gave the stash (if we provided one) as a reference (because it isn’t one), so what can we do?

The solution is easy. Since Git stores stashes as commits1, we are free to tag them like any other commit.

Continuing with the example above:

$ git tag mysettings stash@{1}

Now, reapplying the changes is easy, memorable, and closer to being foolproof:

$ git stash apply mysettings

  1. We can easily verify this by asking Git what type our stash is: git cat-file -t stash@{1}, which returns commit.

2012

Huge year. (Eta Carinae magnitude.)

Back in January I gave a talk on Responsive Web Design for the CWSA. This was my first time speaking, so while I was naturally nervous, nothing prepared me for the shock I received when I saw the CSS legend (and fellow Clevelander) Eric Meyer take a seat among the audience. Sure I could’ve rehearsed more, and of course there were countless improvements to be made, but overall I was satisfied with the talk.

Then, in February, it began.

The planning, the art projects, the phone calls, the insurance policies, the walkthroughs, the meetings, the agendas, the tears, the inspiring nights and weekends at Zygote Press, the arguments, the silliness, the writing, the sampling of delicious foods, the Photoshopping, the web development, the bachelor(ette) parties, the showers, the out-of-town guests, the warmth, the love.

And finally.

After three amazing years and the proposal last November, Laura and I were married at 78th Street Studios in Detroit Shoreway, Cleveland in front of two hundred family members and close friends. It was the best day of my life.

Three months later we spent two weeks honeymooning in Japan. We visited Tokyo, Koyasan, Kyoto, Hiroshima, and Miyajima. Highlights incude attending an afternoon Sumo tournament, hiking the Nakasendō trail from Magome to Tsumago, and spending two nights with a generous Japanese family at their home in Nakatsugawa.

Returning home, I started a new job. A bit unexpected, but it was the right move, and I feel good about where I am in my career right now.

Sadly, this year also brought tragedy. A week before leaving for Japan, we were devastated with the news that our very close friend PJ was diagnosed with terminal stomach cancer. He was given only a few weeks to live, but being an incredibly fit guy, he held on a couple weeks longer than anyone expected, and we got to visit him a few last times before he passed. He represented everything we love about Cleveland, and his influence can be found everywhere in the city. He taught us so much. We really miss you, buddy.

CSS Based fadeOut Effect

Preface

In this post, I will discuss an approach to replace JavaScript based animations with CSS transitions — specifically jQuery’s fadeOut method. The resulting code is not offered as a production ready solution, as it does not account for browser fragmentation or standards adoption. Instead, I am exploring a concept.

Let’s begin

Before CSS3, we relied on JavaScript, or more often the popular library jQuery, to handle our animations.

Animations are great. When properly used they can often increase the user’s understanding of what is happening on the page. For example, removing an element from the page with a fadeout animation is better than instantaneously hiding it.

With jQuery, fading out an element is straightforward:

$('#element').fadeOut();

Simple. But before we move on, let’s talk a little bit about what’s happening above. The jQuery fadeOut method is pretty self-descriptive. It gradually lessens the opacity of the target element — in this case the element with an id element — from 1 (fully opaque) to 0 (fully transparent). Since we did not specify a transition duration or easing function the defaults of 400 milliseconds and swing1 are used respectively. Finally, from the jQuery documentation:

Once the opacity reaches 0, the display style property is set to none, so the element no longer affects the layout of the page.

All is good, but JavaScript powered animations are so old-fashioned. We want to use the new shiny CSS Transitions! Sadly however, things become a little more complicated. Let’s looks at a first attempt at making an element fade out using CSS transitions:

#element {
  transition: opacity 0.4s linear;
}

#element.invisible {
  opacity: 0;
}

So far, so good: whenever the element has the class hidden applied to it (say via a JavaScript event), it will slowly fade out (its opacity will dimish to 0) over a duration of 400 milliseconds. The linear keyword specifies the transition’s easing function.

However, we’re missing the last bit from jQuery’s implementation: once the element is finshed transitioning its opactity propertity we need to remove it from the page flow. jQuery does this by setting the element’s display property to none.

#element.invisible {
  opacity: 0;
  display: none;
}

Hang on! This won’t work. Why? Because the display: none; value will be applied immediately once the #element element acquires the hidden class. You will never see the fadeout effect specified by the transition. The element will be taken out of the page flow before you perceive the animation’s beginning.

What we want is to apply the display: none; property after the CSS transition has completed. How can we do this?

One possible answer would be to use another transition property: transition-delay. A transition delay allows us to offset the beginning of the transition by a specific unit of time. The idea here is to delay removing the element from page flow by the same amount of time we are transitioning the opacity property of the element, and setting its transition duration to 0s. In other words, instantaneously apply the transition but only after a specified delay.

Unfortunately, we hit another snag. Only animatable properties can be the subject of a CSS transition, and the display property isn’t on the list. If the property we wanted to sync with the opacity animations ending time was animatable, we’d be set.2

Looks like we need to use a bit of JavaScript.

The W3 CSS Transitions spec defines a JavaScript transition event system. Ok great! We will now define a new class to be applied upon on transitionend event. Let’s call this opacity-transition-ended. Here’s the JavaScript:

var element = document.getElementById("element");
element.addEventListener("transitionend", function () {
  element.className += " hidden";
}, true);

And define the CSS like so:

#element {
  transition: opacity 0.4s linear;
}

#element.invisible {
  opacity: 0;
}

#element.invisible.hidden {
  display: none;
}

Compatibility

What about compatibility? As this is a CSS3 based approach, browser compatibility is somewhat limited. CSS Transitions are supported in Firefox 4+, Internet Explorer 10+, Safari 3.2+, Chrome 1.0+, and Opera 10.5+. This also means, vendor prefixes and browser specific event names. See this MDN compatibility table for the specifics.


  1. swing is jQuery’s default easing function. Here’s a Stackoverflow conversation describing the swing function as well as a strategy for how to go about implementing it in terms of a CSS transition.

  2. It would be great if the spec allowed you to use non-animatable properties if (and only if) the transition-duration property of the transition was set to 0. That way you wouldn’t need to rely on JavaScript.

Log In

It’s been seventeen years since I started creating things on the web. Today I finally have a home here.

This is for me, but I hope it will be meaningful to others as well.