The Mijingo Blog

Latest news, updates, free tutorials, and more from Mijingo.

How to Install Craft 3

by Ryan Irelan

Now that Craft 3 is available (as of this writing it is still in public beta), it’s time to learn how to install it.

There is one pre-requisite to installing Craft 3:

  • Install and configure Composer

What’s Composer? It’s a dependency management tool for PHP that helps manage software needed for individual projects (as opposed to traditional package managers that let you install software on your computer or server globally.)

Don’t have it installed yet? Watch my video install Composer.

After that you’re ready to install Craft 3. Here’s how:


What is the Element API in Craft CMS?

by Ryan Irelan

The Element API is a first-party plugin by Pixel & Tonic that allows you to create an API for sharing your data from Craft CMS. The responses are formatted as JSON (what is JSON?).

Using the plugin you can create an API that exposes Craft Elements via a JSON-formatted responses. The API only is read-only. You cannot write to Craft using this API and there’s no authentication built in. Be careful what you share!

The Element API is made up of the following pieces:

  • The plugin package itself
  • The elementapi.php file you have to create
  • The code in the file that defines the endpoints and the exposed data

To use the Element API plugin you need to meet these requirements:

  • Craft CMS installed and populated with data you want to expose via the API
  • PHP 5.4 or later (different than the current requirement for Craft CMS)

Installing the Element API plugin is like installing any other Craft plugin: drag the plugin file to the plugins directory and then install the plugin via the Craft Control Panel.

Watch the Free Lesson

How to Create an API with Craft CMS

by Ryan Irelan

In a recent lesson, I walked through how to use the Element API Plugin from Pixel & Tonic to create a JSON API that shares your website’s data (only that data which you choose, of course) for consumption by another website or service.

The free lesson is a fundamental approach to building a read-only API using the default ElementTypes (entry, category, asset, etc) in Craft. As long as you follow my steps, you can get an API up and running quickly.

Toward the end of the lesson, we also learn how to expose your Craft Commerce order data via an API so you can have an outside tool (like a Goole Spreadsheet or reporting tool) ingest it and use it create some sort of report.

Watch the Lesson

Using git-cherry-pick

by Ryan Irelan

Recently I ran into a problem on a project where I was working on the wrong branch and committed changes. Those commits were supposed to go elsewhere and I now I need to get them into the correct branch!

There are a few options to solve this:

  • Merge the incorrect branch into the correct branch. But I don’t want to that because there are items in the incorrect branch that I don’t want. So, that’s out.

  • Recreate those changes in my working branch and just go on with my day. But that’s a waste of my time and I’m adamantly against redoing work!

  • Create a patch and then apply that patch to the new branch.

All solid options but there’s still something better:

$ git cherry-pick

Let’s review where we’re at and then how to solve the problem using git-cherry-pick.

The State of Things

I created a new commit in my repository, in the branch called some_other_feature. But that’s the wrong branch!

$ git branch
*   some_other_feature

The new commit should be on the my_new_feature branch. I could merge the branches but the some_other_feature branch contains commits and changes that I don’t want in the other branch (they are not ready for merging into any upstream branches, like develop or master.

Here’s the commit I need to get into my_new_feature:

commit ec485b624e85b2cad930cf8b7c383a134748b057
Author: Ryan Irelan 
Date:   Fri Aug 19 10:44:47 2016 -0500

    new contact page

Using git-cherry-pick

The syntax of git-cherry-pick is this:

$ git cherry-pick [commit hash]

The first step is fetch the commit hash for the commits we want to cherry-pick. We can do that using git-log and then copying the hash (in full or just the last 7 characters will work) to our clipboard.

Next, we need to be on the branch where we want the changes to be (our destination branch).

$ git checkout my_new_feature

Now we can run the git-cherry-pick command and apply the commit to our destination branch.

$ git cherry-pick ec485b624e85b2cad930cf8b7c383a134748b057

This will return something like this:

[my_new_feature 1bf8955] new contact page
Date: Fri Aug 19 10:44:47 2016 -0500
1 file changed, 1 insertion(+)
create mode 100644 contact.html

If we look at our log for this branch, we now see our commit:

$ git log
commit 1bf8955d5e6ca71633cc57971379e86b9de41916
Author: Ryan Irelan 
Date:   Fri Aug 19 10:44:47 2016 -0500

    new contact page

What’s happening when we run git-cherry-pick?

  • Git is fetching the changes in the specified commit and replaying them in the current branch. The commits are not removed from the source branch; they remain intact.
  • Because this commit is being applied to a new branch and therefore has different contents it will get a different hash than the source commit.

With the problem solved, we are ready to move on with our development work!

Learning More About Git

To learn more about Git check out our Git courses, lessons and tutorials.

Learn more about Git

New Lesson: Using Git in Sublime Text

by Ryan Irelan

A new lesson is available now on how to use Git version control right inside of Sublime Text 3. The goal for this lesson is to learn one way to work a bit more efficiently while coding. There are a few packages available for connecting Git and Sublime Text. In the past I’ve used one called Sublime Text Git and it’s a popular choice. Recently I’ve started using Git Savvy and I really like it so I wanted to share it.

This lesson walks you through installing an using Git Savvy in Sublime Text 3.

Watch the Lesson

Installing Sublime Text Package Control

by Ryan Irelan

Installing packages (add-on functionality that isn't core to the Sublime Text application) in Sublime Text is faster using the Package Control tool.

Package Control isn't part of Sublime Text but an independent project that makes adding additional functionality to Sublime Text easier. If you like Package Control and find yourself depending on it for your work, consider saying thanks to the developer with a small donation to help cover server costs.

To install Package Control on Sublime Text 3, you need input a series of commands into the Sublime Text console. This is actually a Python console but for our needs we just need to paste in a series of commands and Sublime Text will take care of the rest.

Get the Python Code

From the Package Control installation instructions, we grab the Python code to install Package Control. Get the latest version from the site (I could past it here but the code changes with each release and I want to make sure you have the latest code).

Run the Code

To kick of the installation, we run the code in the Sublime Text console.

  1. Type `control-`` to open the console in the bottom portion of the Sublime Text application window.
  2. Paste in the code and press enter.
  3. Once complete and successful, restart Sublime Text.

Type shift-command-p to open the command palate and type:

package control

If you see options for Package Control (like Package Control: Install Package) then Package is properly installed.

Sometimes the tool doesn't install properly. If this happens to you, use the manual installation instructions instead.

Export Files from a Git Repository

by Ryan Irelan

In this free lesson video, Ryan walks through how to use the git-archive command to export the files from a Git repository into a ZIP file.

Watch the lesson on archiving files from Git

Ready to learn more about Git?

We have more courses, articles, and tutorials on Git. Start learning immediately!

See the courses

Brief Overview of Craft Routing to Templates

by Ryan Irelan

How does Craft know which template to render when? It all starts and ends with Craft’s request routing.

The Craft documentation for Routing starts us off perfectly:

When a request comes in, Craft goes through several checks when determining where to route the request.

Craft does a routing check sequence that every request goes through so it ends up at the right place, delivering the right page or asset.

Pull up the routing documentation page and let’s talk through it.

The first three checks in the routing sequence:

  • “Should Craft handle this request in the first place?”
  • “Is it a resource request?”
  • “Is it an action request?”

cover whether Craft should take the request at all (sometimes it’s not necessary), if it’s a request for a Craft-managed resource, or if it’s an action request (like submitting a form or other actions from third-party plugins).

The fourth check is if the request is for an entry or category page. If there is a URI match then Craft will load the proper template (the one you specified when setting up the category or section).

The fifth check is if the request matches any Dynamic Routes you set up in the Craft control panel. Dynamic routes are hugely powerful in allowing you to create custom URIs that don’t necessarily match the template path. This saves you from having to conceive an unusual template directory and file naming scheme just to get the URLs to be how you want. If there is a match then Craft will render the template specified in the matching Dynamic Route.

The second-to-last check in the sequence to see if the request URI matches a template. If the URI is a valid template path (directory + template), then Craft will render that template.

This is a literal routing of the URI to the template.

If you have a request for template offices/austin.html and Craft goes through its checks and doesn’t find a match before it gets to the template check then it will render the offices/austin.html template. If you had an entry with that URI then it would render the entry instead (using whichever section entry template you specified).

At the end of the check sequence, if there are no matches, Craft will return a 404 error. If you don’t have a custom 404 template, Craft will render the default view. To create a custom 404 template, add a 404.html template file in the root of your craft/templates directory and Craft will use it.

Ready to learn more about the Craft CMS?

My Craft Starter Pack is 4 ½ hours of premium learning that will get you started building sites with Craft for yourself, your company, or your clients.

Get Immediate Access

Sublime Text Tips and Plugins

by Ryan Irelan

Magnus Gyllenswärd of Thoughtbot did a short overview of some of the features and plugins he uses and likes in Sublime Text as part of his Thoughtbot Lunchtime Lightning presentation.

Here are some of the things he covers:

  • Fetch - fetch remote files from anywhere
  • Gist from condemil, create and edit Gists.
  • Less Tabs from Web Artisan. Remove tabs that you haven’t used in a while.
  • Emmet - Official plugin for Sublime Text for writing markup faster.
  • Multiple cursors - a flagship feature of Sublime Text. Memorize this if you don’t know it already.
  • Sublime Text Projects - a feature I don’t really use but probably should!
  • Can I Use plugin, that lets you highlight a property and see its support on

By the way, if your company doesn’t do lunch time talks where you share information and techniques internally, I strongly encourage it. Whether you call them Lunchtime Lightning talks, Lunch ‘n’ Learns—as they were at my previous company—or no name at all, these gatherings are a way to rapidly transfer knowledge among team members. Very valuable!

(Link via Gabe at Macdrifter)

How to install Gulp.js

by Ryan Irelan

Just like its JavaScript Task Runner neighbor Grunt, Gulp also makes it simple (and fast!) to automate those really annoying web development tasks, like concatenating files, processing Sass, minifying JavaScript files, or optimizing batches of images.

In this tutorial, we’ll learn how to install Gulp.js.

Just like with Grunt, our first dependency is Node.js, so the video will start there. I’ll continue on after the video with some more steps to get set up.

Once inside the project where you want to run Gulp (you can get project shown in the video as part of the JavaScript Task Runners course I put together), we need to create a package.json file that we’ll use to define the decencies for the project, including Gulp.

We’ll do that on the command line using:

npm init

which will walk us through the process by asking some questions about our project. Once we’re done with the questions, npm will generate the package.json file for us, saving it at the root of our project.

We want to save Gulp as a dependency for our project, so in the project root we run:

npm install gulp --save-dev

We use --save-dev so the module is saved in package.json as a dependancy. When someone else wants to work on the project on their computer, they can run nom install and all of the dependencies listed in package.json will be installed automatically.

After the installation of Gulp is done, you should see some output and then a new command prompt.

We look at the package.json file and we see that gulp was added as a dependency for this project.

To ensure that Gulp is available for us on the command line, we need to install it globally:

npm install gulp -g

Running Gulp will now work for us, inside the project:


That should output:

[08:29:38] No gulpfile found

because we don’t yet have a Gulpfile.js file defining our Gulp tasks.

Creating a Gulpfile.js File

Either create a new file in your favorite code editor (right in the root of the project, alongside the package.json file), or do it in the command line:

touch Gulpfile.js

Now when we run Gulp:


We should get a bit more output, like this:

[08:33:46] Using gulpfile ~/projects/test-project/Gulpfile.js
[08:33:47] Task 'default' is not in your gulpfile
[08:33:47] Please check the documentation for proper gulpfile formatting

Gulp now sees our Gulpfile.js file but there’s nothing in it. At the very least, Gulp needs a default task to run when we use the plain gulp command. Let’s add one, shall we?

Open up the Gulpfile.js file and add the following to it:

var gulp = require('gulp');

gulp.task('default', function() {
    // Code for the default task

We have to first require gulp at the top of the file, so we can use Gulp to run our tasks. After that, we define our default Gulp task. The task is empty (containing only a code comment) but it will be enough to check that Gulp is running properly.

Save the file changes and the pop back onto the command line and re-run gulp:


You should now see more output from Gulp, this time showing that it ran the default task:

[08:43:04] Using gulpfile ~/projects/test-project/Gulpfile.js
[08:43:04] Starting 'default'...
[08:43:04] Finished 'default' after 79 μs

Now you’re ready to start defining your own Gulp tasks and automate those pesky development chores!

Learn More About Grunt & Gulp

My video course will get you up and running on both task runners in just 90 minutes.

Get the Grunt & Gulp video course

How to Install Grunt

by Ryan Irelan

Installing Grunt is the first step to automating your web development workflow with a JavaScript Task Runner and it takes just a few steps.

Here’s a video of the steps (pulled right from the course). The written steps are also below.

To install Grunt we need to use the command line.

  • Install Node.js. Using the big green button on the NodeJS site, download the installer package for your operating system. This includes NPM or Node Package Manager, which we also need to manage our Grunt plugins.
  • We do want to make sure we are up to date with npm. So, first, run:
npm update -g npm
  • Now we can install the Grunt command line tool using npm:
sudo npm install -g grunt-cli

This will install the grunt command line tool in your system path and allow it to be run from anywhere on your system. It doesn’t install Grunt, just allows us to run the local project version of Grunt from the command line.

Learn More About Grunt & Gulp

My video course will get you up and running on both task runners in just 90 minutes.

Get the Grunt & Gulp video course

Git Aliases in .bash_profile

by Ryan Irelan

Learn how to add system-wide Git aliases to your .bash_profile that allow you to:

  • create a shortcut to quickly push changes to the develop branch of your project
  • quickly push to the master branch using a bash alias
  • stage a boatload of files (added and deleted) with one five-letter command. This is perfect to large updates to CMSes, frameworks, and web apps.

This 7 minute video is an excerpt from the OS X Shell Tricks course.

Three Twig Tag Types in Craft CMS Explained

by Ryan Irelan

Templating in Craft using Twig can, at first, be a little confusing. If you, like me, come from other systems that have a proprietary template tag system, then it might take a little time to wrap your head around how Craft and Twig work.

But once we learn about the different types of tags things will be clearer and you’ll discover the power of using Twig in Craft. This tutorial will give you the direction and guidance you need to get started.

Let’s jump right in.

There are three tag types in Twig and Craft:

  • Statement/Logic Tags
  • Output Tags
  • Comment Tags

You will always use the first two in your Craft templates. The third, comment tags, are optional but a handy way of documenting anything that isn’t obvious by reading the code.

Statement/Logic Tags

Statement or logic tags use the curly brace plus percent sign delimiter. In Twig and Craft they can come in multiple forms.

Some are just a single tag, like this Craft-specific Twig tag:

{% requireLogin %}

which you would put at the top of a template in Craft to require a logged-in state. If a visitor is not logged in than Craft will automatically redirect them to the log-in page.

Other logic tags take parameters, like the redirect tag in Craft:

{% redirect "about/tos" %}

The redirect tag takes one parameter, which is the URL or path to where you want to redirect the visitor. This is a tag specific to Craft but there are some Twig tags you should know, too.

Another type of tag is one that has an opening and closing tag, like the for tag in Craft.

{% for %}
{% endfor %}

The tag pairs have an opening tag and a closing tag. The closing tag will typically have an “end” prefix, like endfor, endpaginate, and endblock.

Even the set tag we use to set a variable can be used as a tag pair. The simple version looks like this:

{% set author = "Ryan Irelan" %}

But using a tag pair for set, you can assign a block of text to a variable. Here we’re setting the variable socialLinks to an unordered list of social network links:

{% set socialLinks %}
<ul class="social">
    <li class="twitter"><a href="">Twitter</a></li>
    <li class="facebook"><a href="">Facebook</a></li>
    <li class="googleplus"><a href="">Google+</a></li>
{% endset %}

Another example of a tag pair–and by far your most used tag while writing Twig template code for Craft–is the for-loop. It’s how you will loop through and display section entries in your templates and output other lists, like categories.

This is a for-loop to display content from an array of blog posts:

{% for entry in craft.entries.section('blog') %}
    {{ entry.body }}
{% endfor %}

It uses the curly brace plus percent sign delimiter for both the opening and closing tags of the for-loop. This delimiter tells Twig that what’s between needs to be executed as a statement (in this case a for-loop).

Output Tags

The code with the double curly braces are output tags. They print variable contents to the screen (i.e. output content in your template).

{{ author }}

The author variable would output my name (because we set it in the previous example).

If you want to use an output tag to pass in data to another tag, like when we set a variable in Twig, then you don’t need to use the double curly braces.

{% set name = author %}

If we printed out the value of the name variable we just set than it would render:

Ryan Irelan

But output tags can generate the output on the fly and then print it to the screen. How about a little math?

{{ 4 * 4 }}

This output tag will do the multiplication of 4 and 4 and print out the product. I’m unsure how practical it is to do math like this in the template but there you have it.

The Twig documentation calls out that the curly braces are not part of the variable itself but instead an indicator that the value of the variable contained within should printed to the screen.

Comment Tags

This tag type is straight-forward but perfect for adding comments to your templates but not have those comments render in the page source like HTML comments would.

{# Begin logic for sidebar #}

Using a single opening curly brace paired with a pound sign, we can create the un-rendered comments. They’ll always be available in your template file but never rendered by Twig.

Any code that is inside the comment tag will not be executed by Twig.

{# removing this for now to debug
    {% for entry in entries %}
        {{ entry.body }}
    {% endfor %}

There’s a lot more to templating with Twig in Craft but this introduction to three different tags will get you set off in the right direction.

Don’t miss my new course on Craft + Twig

Coming soon is a brand new video course on Twig & Craft that will help you grasp what Twig is, how Craft and Twig work together, and some templating best practices. Sign up below to get notified when the course is ready!

Ready to learn more about Craft?

If you want to learn more right now about Craft, I have a popular 2 ½ hour video course that will get you started on the right path.

Get the Craft video course

Important SVG Elements

by Ryan Irelan

There are a lot of elements–and attributes–to consider when writing SVG. But to get started, we don’t have to learn them all. Let’s review the most important ones you’ll encounter while working with generated SVG or SVG you coded yourself.

svg Element

You’re probably already very familiar with this. It’s the main element of SVG and inside of which you nest any shapes, paths, lines, etc. that you want to draw.

The SVG element defines the viewport or canvas for SVG content.

Here are some of the specific attributes for svg:

  • height - the height of the viewport
  • preserveAspectRatio - forces the aspect ratio so your image isn’t stretched when using the viewBox element to define a new coordinate system.
  • viewBox- Allows you to set a new coordinate system by defining where x,y coordinates where the system starts as well as the width and height.
  • width - The width of the viewport for this SVG element.

g Element

This element is used to create groups of SVG objects. For example, if you had a series of related rectangles (rect), you can group them together inside of a g element. The nice thing about this is that any transformations you apply to g apply to everything inside of the group.

The g element accepts all global attributes (like stroke, fill, etc).

circle Element

This element does exactly what it says in the name: it creates circles.

circle accepts three element-specific attributes:

  • cx - This attribute defines the x coordinate of the center of the shape.
  • cy - This attribute defines the y coordinate of the center of the shape.
  • r - Defines the radius of the circle.

rect Element

This is the elements we used in all our examples up to this point. It creates rectangles.

The rect elements takes the following attributes:

  • height - Defines the height the shape.
  • width - Defines the width of the shape.
  • x - The x coordinate where the shape should start drawing.
  • y - The y coordinate where the shape should start drawing.

line Element

The line element allows you to draw lines in SVG. Each line connects two points by setting x and y coordinates.

Here are the attributes available in line:

  • x1 - the start of the line on the x axis
  • y1 - the start of the line on the y axis
  • x2 - the end of the line on the x axis
  • y2 - the end of the line on the y axis

path Element

You’ll see the path element if you take an existing artwork and convert it to SVG (in Adobe Illustrator, for example). Illustrator converts the artwork to SVG by tracing the shapes in the image and converting them to SVG path elements.

Any shape can be created with the path element. It takes the following specific attributes:

  • d - this is the definition attribute, which defines the path to follow to create the shape. The path is defined using “path descriptions:” Moveto, Lineto, Curveto, Arcto, ClosePath.
  • pathLength - Use this attribute to define the total length of the path.

polygon Element

The polygon elements allows you to create any shape with many sides. A typical example would be an octagon. You plot the sides of the polygon using points (the only specific attribute for this element).

text Element

Use the text element to set text in your SVG. text takes the global style attribute, which you can use to apply styles (size, font, stroke, etc) to the text.

  • dx -
  • dy -
  • lengthAdjust -
  • text-anchor -
  • textLength - An exact value of the length of the text. This used for very specific layouts.
  • rotate - A list of numbers that will determine the rotation of the text.
  • x - the coordinate where the text begins
  • y - the coordinate where the text begins

textPath Element

The textPath element allows you to put text along a path element and have the text follow the shape. This is a classic SVG demo element because it can make text on a curve.

Did you like this review of SVG elements?

Invest a small amount of time to improve how you use SVG with our hands-on video course, Up and Running with SVG.

Get the video course

Search Git Commits with grep

by Ryan Irelan

A log of commits in Git (retrieved using git-log) can be filtered and changed to output only the commits (or types of commits) that we want to see.

Typically, you review the repository history using git-log by running:

git log

The default log is great for grabbing a quick look at what just happened in the repository. But it takes up a lot space and you can only see a handful of commits at once, unless you have a display the size of a building.

Sometimes, however, we want to only find changes that included certain keywords in the commit message. To do this we use the --grep option and pass in a term or regular expression.

git log --grep="homepage"

This will return a log with commits that only reference the word “homepage” in the commit message.

Used in conjunction with other git-log options (like --author and --since), you can very quickly narrow down the commits to exactly what you’re looking for.

Ready to learn more about Git?

Invest a small amount of time to improve how you use Git with our practical tutorial.

Get the video course

Grunt & Gulp Together (at last)

by Ryan Irelan

We’ve been learning about both Grunt and Gulp with the Mijingo JavaScript Task Runners course.

Two powerful tools, right?

As I mention in the introduction video, you don’t have to choose between the two. Use Grunt for this project and Gulp for that other project. 

Or use them together!

This short tutorial tells you how. Let’s get started.

Joining Gulp and Grunt

You make Grunt and Gulp work together by running your Grunt tasks in your gulpfile.js file. You’ll need to do the following steps in a project already set up with Gulp. Since you learned with the Mijingo course, you can just open up the Gulp project you built in the course and start there.

Install the Node package gulp-grunt by running:

npm install gulp-grunt --save-dev

If it’s not there already, move your Gruntfile.js file to the project (if you’re using the sample project from the course you’ll want to copy it over). We need it there so we can access the tasks inside of Gulp.

We have to make sure the Grunt plugins are installed so the Grunt tasks can run. No Grunt plugins, no Grunt tasks.

Individually install the Grunt plugins you need, or copy the dependencies from package.json in the Grunt project to package.json in the Gulp project.

Because we have added new dependencies, we need to install them in the project. Run

npm install

to install all project dependencies, including the Grunt plugins we just added to the package.json files.

Near the top of your Gulp file, require the gulp-grunt plugin like so:


Because we’re calling gulp, we need to do this after we define the gulp variable. This loads in the Grunt tasks defined in your Gruntfile.js file. Now we have access to them and can call them from our Gulp file.

Before we do, let’s make sure everything is working okay with our Gulp file. Let’s run gulp in the command line as a test to check.


Look good? No errors? Good, let’s continue.

Now we need to tell Gulp to run our Grunt tasks. We’ll add the Grunt task sass:dist to the default Gulp task. It will look like this:

gulp.task('default', function() {
    gulp.start('uglify', 'sass', 'grunt-sass:dist');

We added the Grunt sass:dist task to the default Gulp tasks by specifying it in the start method.

All Grunt tasks run in Gulp will use the grunt- prefix so they don’t conflict with your Gulp tasks of the same name. You don’t have to rename your Grunt tasks to make this happen, gulp-grunt will handle this prefixing automatically.

Now for the grand finale. Let’s run the Grunt task in Gulp.

Run gulp in Terminal to fire off the default Gulp task.


At the end of the output you should see something like this:

Running "sass:dist" (sass) task

Done, without errors.
[20:38:24] Finished 'grunt-sass:dist' after 1.2 s

That’s it, you did it!

Further Reading

To learn about all of the options for using the gulp-grunt Gulp plugin, review the official documentation.

Learn More About Grunt & Gulp

My video course will get you up and running on both task runners in just 90 minutes.

Get the Grunt & Gulp video course

Two Types of Git Tags

by Ryan Irelan

There are types of tags in Git: annotated and non-annotated. The names say it all: with one type we tag with an annotation on what the tag is about, while the other is tag without annotation. Both, however, are tags and mark a point of time in the life of the repository.

Annotated Tags

Annotated tags are created with a message so there’s some context–other than the name of the tag–to go with the tag.

git tag v1.2.0 -m "version 1.2.0, including new API"

In addition to the message, annotated tags also include the name of the tagger, and the date the tag was created.

If we run

git show v1.2.0

we will get something like this above the list of changes:

tag v1.2.0
Tagger: Sally Smith 
Date:   Tue Jan 27 14:06:02 2015 -0600

version 1.2.0 of the site

Non-annotated Tags

Non-annotated tags (also called “lightweight tags”) are created without a message, so the only hint as to what the tag is about is how you name it.

git tag v1.2.1

Non-annotated tags will look like a commit object, showing the changes made to the repository, but it won’t have metadata about the tag.

When do I use which tag type?

That short answer is: that’s entirely up to you.

But if you want to include the name of the tagger and a date, you should use the annotated tag. I would use annotated tags for official releases, like MySoftware v1.2.1.

git tag MySoftware-v1.2.1 -m "version 1.2.1, including new API"

This tag shows the tagger name and date, in additional to any information about the release.

For casual tagging, a lightweight or non-annotated tag should be enough.

Both tag types include the entire history log of commits, so you will always have a record of what happened leading up to the tag (remember, a tag is just a snapshot of a point in time in the life of a repository).

Ready to learn more about Git?

Get the video course

Reverting a Git Merge

by Ryan Irelan

Sometimes you get in a situation–and this is a no-judgement zone, we’ve all been there–where you merge branches and you messed up and need to undo the merge because, well, because your co-workers are kind of mad you broke the project.

Let’s say that happened. How do you revert a merge?

We have a my_feature_branch that I’ve been working in. We also have a develop branch that I merge into and deploy to my testing/staging server.

git checkout develop
git merge my_feature_branch

My merge of my_feature_branch into develop broke the site. I need to save myself from further embarrassment in front of my team, so let’s undo the merge into develop.

Because the merge is a commit that points the HEAD to a specific commit, we can undo the merge commit and roll back to the pre-merge state.

To revert the previous commit (our merge commit), we do:

git revert HEAD

We can also specify the exact merge commit that we want to revert using the same revert command but with a couple additional options.

git revert -m 1 dd8d6f587fa24327d5f5afd6fa8c3e604189c8d4>

We specify the merge using the SHA1 hash of the merge commit. The -m followed by the 1 indicates that we want to keep the parent side of the merge (the branch we are merging into).

The outcome of this revert is that Git will create a new commit that rolls back the changes from the merge.

We are saved from embarrassment! The project is working again. Now back to work to figure out why that merge broke the commit.

Ready to learn more about Git?

Get the video course

Find Out What A Command Does

by Ryan Irelan

In the command line, you’ll often find yourself wondering exactly what some command does, what the options are, and how, just maybe, you can make your use of that command even better. Here’s how to do it.

The first place I always look when needing more information about the command is the manual (or man as the cool kids might refer to it). Most well-maintained and well-documented tools will have robust manual pages for you to review.

Let’s say we need to know more about git-reset, a tool in Git that allows you to (destructively) rollback changes to your repository.

I know the command is git reset and if add the --help option to it, I’ll get the manual for git-reset.

git reset --help

In the case of git-reset, we get a healthy amount of well-written documentation and very, very helpful Examples area. The examples provided offer real-world scenarios you might face, right from the folks who are working on the Git source code.

Manual for git-reset

Another way to get help with a command is to use the man command:

man ssh

This will display the manual for the SSH command (note that ssh --help does not work).

Not every tool has as robust a manual as Git and SSH but most all do, and you can learn a lot from them. Next time you get stuck, check out the manual!

Want to learn more about the command line? Our Command Line Fundamentals course will get you started on the path to success.

Adding Your Completed Courses to LinkedIn

by Ryan Irelan

An important way to show ongoing professional improvement is by using LinkedIn’s Courses listing. Courses is a section in your LinkedIn profile where you can list the training courses you took online, in person, or at a traditional school.

Adding Mijingo courses to LinkedIn

The major driving force behind Mijingo is to provide you tools and training to continue your professional development. And, you know, it’s important to show that you’re always learning, improving, and staying on top of new techniques in your field.

Let’s make sure you can show what you’ve learned!

To add Mijingo courses you’ve completed to your LinkedIn profile, follow these steps:

  1. Log in to LinkedIn
  2. Under Profile menu, choose Edit Profile
  3. Right under your profile overview, you should see “Add a section to your profile”. Click View More and then choose Courses to add the Courses section to your profile.
  4. Click “Add course” to add a new course. For the course name, use the full name of the course on and append “from Mijingo” at the end. E.g. “Up and Running with SVG from Mijingo”. Leave the course number blank. Lastly, associate it with the position you have or had while taking the course.

Once you’ve added courses that you’ve successfully completed, save your additions and then review your profile to ensure everything looks correct.

Next Page

What are our customers saying?

"Just purchased your Flexible Twig course. Love it!"
Tyler Morrison
"Been enjoying @mijingo 's Learning Craft video tutorials. Feeling like I've got a good basic understanding of #craftcms Very impressive"
Laura Montgomery
"I bought your Craft Starter Pack a year and a half ago. Worth every dollar. In fact, I would've paid twice as much for it, because you saved me so much time."
Timothy Ingram
"Ben's knowledge of Craft combined with his relaxed and informal teaching style makes for a great learning experience."
Steve Abraham
"Ben puts a lot of thought into his teaching approach and has the ability to explain complex concepts in a way that just make sense"
Gareth Redfern
"Ben is great at taking a complex subject and breaking it down in a way that you can wrap your mind around. I thought that plugin development was something I would never understand, and happily Ben proved me wrong!"
Jonathan Melville
"I really appreciate all the videos and writing you have done. Your work has given me a jump start on my front end development business."
Shan Ricciardi

Perfect for Small Teams & Companies

Mijingo's courses are perfect as the training curriculum for both small teams and entire companies.

Our courses are offered in Team Packs (up to 5 people) and Company Packs (up to 25 people), so you can make one simple, fast purchase to train your entire staff.

Prices are listed with each course. Need more than 25 or something custom?

Send Your Requirements
Team Pack2-5 People
Company Pack6-25 People
Custom Pack25+ People