The Mijingo Blog

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

Preventing Fast-Forward Git Merges

by Ryan Irelan

I’ve written about why you shouldn’t use fast forward Git merges before. In short, using non-fast forward merges keeps your history complete and intact. Using the --no-ff option will prevent you from merging branches and having the child branch history get the boot.

In my PeersConf workshop recently I covered this again. My internet friend Stephen Lewis had a good solution for making sure that Git always uses non-fast forward merges.

git config --global --add merge.ff false

I just added it to my global config; please consider adding it to yours.

Pick Your Tools and Use Them

by Ryan Irelan

From a recent Twitter series I shared:

Not everyone likes Sass or wants to use Grunt or even likes a CMS. That’s okay. If the tools help you, use them.

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.

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

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

Learn more advanced Git techniques

by Ryan Irelan

Today I released a brand new course called Git: The Next Steps. It’s a follow-up to the Basics of Git course that gets you up and running with Git version control.

The course has three modules: How Git Works, Git Workflow Tools, and Solving Problems with Git.

We start out with digging in and learning how Git works and why it really is just a bunch of interrelated commit objects (what? you’ll see what I mean when you take the course).

The workflow tools module gives you practical Git commands that will help you immediately. A cool way to create useful, helpful Git log output, merging stashing, and tagging.

Module 3 gives you information for when things go wrong. Because they will go wrong! Learn all about git-bisect, git-revert, and git-reset.

There’s a lot more to learn about Git and this course will take you to the next step.

Start learning Git now

Saving Changes with Git Stash

by Ryan Irelan

In the Basics of Git course, I was in the middle of making some changes to the homepage of our sample site when a another change request came in. I needed to quickly save–or stash away–my changes and then apply them back to the repository later, after my other work was complete.

The easiest way to do this is with git-stash, a useful git command that allows you to store the modifications you’ve made in our working directory and go back to a clean working directory.

From the Git Manual (run git stash --help to see it on your own):

Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory. The command saves your local modifications away and reverts the working directory to match the HEAD commit.

Git stash isn’t a replacement for smart use of branches (we don’t want to start a new feature in a main branch and then stash it away until you’re ready to apply it) but can be a life saver if we find ourselves needing to quickly shifting gears to another task, bug report, or request.

git stash list

Fire up a current project to try out git stash.

First, let’s check if we have any existing stashes.

git stash list

The list option shows all of the existing stashes, if there are any. If you do have some they’ll be listed like this:


stash@{0}: On develop: testing out git stash
stash@{1}: WIP on master: 4fd1101 fixing layout on homepage product listing
stash@{2}: On develop: product bundle download template

Each stash is listed in a separate line, starting with the stash name that consists of the word “stash” and an index (starting with zero) in curly braces. The latest stash is the one at the top, with the index of zero (confusing, right?).

Let’s add a stash. To do that we use the stash savecommand.

stash save "updated the offline file"

The last two parts of that stash command are optional. We can just do:

stash

instead and it will still create a stash with any changes in the working directory but without are customized message. The save option is automatically assumed if it isn’t included.

Here’s the list of stashes now:


stash@{0}: On develop: updated the offline file
stash@{1}: On develop: testing out git stash
stash@{2}: WIP on master: 4fd1101 fixing layout on homepage product listing
stash@{3}: On develop: product bundle download template

To apply a stash to the working directory, we have a couple of options. The first is:

git stash pop

which will remove the most recent stash from the list and apply it to the current working directory. It’s just reversing what you did when saving the stash (but keeping any subsequent repository changes intact).

You can also be specific and pop any stash in the list:

git stash pop stash@{1}

We should see something like this at the end of the output:

Dropped stash@{0} (38f88c1479dc8a3c63f794feed7cd276ae3c6c7e)

The other option when applying a stash is to use:

git stash apply

Just like with pop, we can choose to not specify a stash and it will use the latest. Or, we can specify one, like this:

git stash apply stash@{1}

With apply, we’ll get similar output when applying the stash, but without the message that the stash was dropped. Why? Because git stash apply applies the stash we specified but it doesn’t drop it from the list of stashes.

If we run:

git stash list

We get the full list of stashes, including the one we just applied.


stash@{0}: On develop: updated the offline file
stash@{1}: On develop: testing out git stash
stash@{2}: WIP on master: 4fd1101 fixing layout on homepage product listing
stash@{3}: On develop: product bundle download template

These are the basic commands when using stashes day-to-day. There’s more to it, and I encourage you to run:

git stash --help

to see all of the commands.

Do you need a primer on Git? Check out our course Basics of Git to get started today.

Why You Shouldn’t Use Git Fast Forward

by Ryan Irelan

I’ve been using the Git Flow branching model for a while (but at times not very strict). Maybe because it’s buried in the original article but I didn’t realize until now that there’s a very good reason to not allow fast-forwards when merging branches.

The –no-ff flag causes the merge to always create a new commit object, even if the merge could be performed with a fast-forward. This avoids losing information about the historical existence of a feature branch and groups together all commits that together added the feature.

If you do git merge without the --no-ff option then

it is impossible to see from the Git history which of the commit objects together have implemented a feature—you would have to manually read all the log messages. Reverting a whole feature (i.e. a group of commits), is a true headache in the latter situation, whereas it is easily done if the –no-ff flag was used.

I’ve been there. Using --no-ff would’ve saved me a lot of time.

If you aren’t already familiar with it, Vincent’s A successful Git branching model is a canonical article on using Git.

Previous 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