The Mijingo Blog

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

Using Git Hooks

by Ryan Irelan

Git hooks are similar to SVN hooks; you can execute a script at a point in the Git routine. Git hooks are both local and server-side. The local hooks pertain to local activities, like committing, merging, checking out, etc. The server-side hooks deal with receiving pushes from a local client.

The scripts that Git hooks execute are stored in the .git/hooks directory of your project. In every repository there are a collection of sample hooks that you can rename and use as inspiration for your own.

The scripts can be in any language that support executable scripts. The samples are mostly shell scripts, but you can use Perl, Ruby, Python, or something else that is familiar to you.

Here are all the hooks available in Git:

  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • applypatch-msg
  • pre-applypatch
  • post-applypath
  • pre-rebase
  • post-rewrite
  • post-checkout
  • post-merge
  • pre-push
  • pre-receive
  • update
  • post-receive

Local Git Hooks

Local Git hooks reside in the .git/hooks directory and are not treated as project files. They are not tracked in the Index and because of that they are not included when someone clones a repository.

Because of this there are some limitations to keep in mind while working with Git hooks. First and foremost: local hooks are not a reliable way to enforce policies, like a commit message structure. And, because you are unable to include the contents of the .git/hooks directory in version control, you will need to consider a way to share hooks that you’d like your team to use.

Here are the local hooks:

  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • applypatch-msg
  • pre-applypatch
  • post-applypath
  • pre-rebase
  • post-rewrite
  • post-checkout
  • post-merge
  • pre-push

Server-side Hooks

Server-side hooks are set up to kick off scripts when a typical remote repository actions takes place.

There are only three server-side hooks:

  • pre-receive
  • update
  • post-receive

They all operate around when the server receives a git-push from a client. These are reliable methods for enforcing some sort of repository or standard. You can run checks, kick of an integration script, testing, etc.

Implement a Git Hook

For our example we’re going to implement a local hook. We’d like to display a message after each commit, reminding us to push our commits to the remote repository.

The setup for this message will be to use the post-commit hook. This hook is triggered after each successful commit. For our implementation, we want the hook to trigger and display a message for us. 
There isn’t a sample file for post-commit already in place. That’s okay, we can create it.

Create a new file called post-commit in .git/hooks.

I’m going to use Ruby as the scripting language. Remember, Git Hooks can use any executable script. But I like Ruby so we’ll use that. This Ruby code is as simple as it comes, with just a single puts statement.

Add this code to the post-commit file:


#!/usr/local/bin
puts "======================="
puts "Please remember to push your commits!"
puts "======================="

With the code in place, we can then save the hook file and set it as executable.


$ chmod +x post-commit

Test it by making a change to our project and creating a commit. If you see the message, it worked!

If you didn’t, check your code, that the hook file is executable, and that you have it properly named.

In another article I’ll talk about triggering hooks on the server.

Git the Essentials

Learn everything you need to be proficient in Git. 40+ videos, 6 hours of learning, a better understanding of Git.

Get Git Essentials

Git Merge Therapy

by Ryan Irelan

Have a seat on the sofa for a moment, please. I want share something important with you.

Ready?

Git merge conflicts are normal and okay.

They are supposed to happen and, most likely, will happen regularly. They don’t happen because you did something wrong. They happen because Git is trying to protect you from losing your hard work.

If you’re new to Git or haven’t done extensive work with it in a team environment then you probably haven’t had the experience of a lot of merge conflicts.

In a future article I will share how you can resolve conflicts but right now, let’s talk about prevention.

We can do some things to prevent conflicts; here’s a list of a few:

  • Ignore generated files
  • Ignore cache or other runtime directories and files
  • Have a good branching strategy
  • Avoid whitespace errors

I’ll go into each one in detail in future articles.

Until then: Git conflicts are okay!

Git the Essentials

Learn everything you need to be proficient in Git. 40+ videos, 6 hours of learning, a better understanding of Git.

Get Git Essentials

The Big Picture of Git

by Ryan Irelan

When starting out with Git, it’s much easier to understand how to use it if we also understand the basics of what Git is.

By that I mean what Git is beyond the commands. Conceptually speaking.

What is a Version Control System (VCS)?

Git is a version control system. You’ll hear this referred to as a VCS sometimes. This is a general term to describe tools that track changes to files over a period of time. The reason we track the changes is so we can revert to previous versions, have a log of the work that was completed, as well as have an incremental backup of the project.

Version control systems aren’t just for code but that’s where they got their start and are most widely used.

You could–and I have–use version control for a book you’re writing.

You could use version control for designs you’re creating for a project.

You could use version control for a series of documents, like proposals, contracts, or agreements.

If it’s a file, it can be tracked by a version control system.

Okay, great. So why should use a version control system for your projects?

First and foremost is because it’s a reliable way to track changes to your files. You might’ve used a simple version control system in the past where you zipped up a project and put a date on it, thereby capturing that day’s work. A version control system also lets you snapshot changes to the project but in a more structured and reliable way.

Getting Git

There are lot of other version control systems out there and perhaps you’ve used one or two before. In the past I’ve used CVS, Subversion, and Mercurial, in addition to Git. I prefer Git because it is local, simple, and fast.

So let’s talk briefly and at a high level of how Git works.

Snapshots of Your Project

When you initialize a new Git repository, you are telling Git to track a set of files.

This set of files will be in a common directory (and subdirectories).

Git now cares about what happens to those files.

At first Git will just tell you that it sees a bunch of files but isn’t yet tracking them. It’ll be up to you to add those files so Git will care about them on an individual basis. After that, Git will notice every change to the file.

By initializing a Git repository, you tell Git: “Hey I want you to pay attention to this set of files. If you don’t know about a file yet, please tell me. If something changes in a file, please tell me. In return, I’ll commit those changes to your repository so you are aware.

Let me try an analogy and see if this works.

Imagine you’re a summer camp counselor. Your job is to take care of, educate, and otherwise entertain a specific group of kids. The kids are organized into groups.

You arrive at the camp on Day 1 and you know you’re responsible for a group of kids. You walk into the room and your supervisor says: “Okay, Ryan, this is your group.”

You look out at the group of kids and say “Okay, ya’ll are mine. I will take care of you.”

“First order of business. I see I have 15 kids here. But I don’t know your names. I need you to form a line and then give me your names so I can write them on this list. This is the list I will use to track your progress at camp so I can report back to your parents when they pick you up on Sunday.”

The kids form a line and, one by one, they give you their name and you write it down on the paper attached to your clipboard. You now have them tracked and know exactly who the kids are.

As summer camp goes on, you watch your campers and their actives. If Suzanne swims a 1km lap in the lake, you mark that change down next to her name on the list.

If Albert gets sick because he ate too many bowls of chocolate pudding after dinner, then you mark that down next to his name to track his health.

The bottom line is: you are watching these kids and tracking how they change during their time at camp.

This analogy may be a little thin but I hope you get the idea. Key takeaway: Think about Git as a system that watches a set of files you tell it to.

This is the git init command.

Once you tell it to watch a set of files, you then have to introduce it to each file.

This is the git add command.

(I go over the actual commands in my Git Essentials course bundle.)

Just like with the campers and and counselor, think about your Git repository as the set of files. Every time you make a change to a file and commit that change (record it as a change), Git snapshots the state of the entire collection of files at that moment.

This might sound like Git is just zipping up the files and such. It’s much more nuanced than that (and it’s something we cover in the Git: Under the Hood course).

Git only saves and records changes to the files that have changed. For the other files, the snapshot simply points to the previous snapshot. This allows Git to efficiently store files without becoming unnecessarily large over the lifecycle of a project.

So, what is Git doing?

It’s caring about your project files because you told it to. Every time you work with Git think of it in this way. Git cares a lot and sometimes you have to tell it no longer care (git ignore), too.

And, as you’ll learn in a different video on merging branches in Git, Git cares so much that it won’t let you lose changes or work. It really is looking out for you.

What this in video form

Git the Essentials

Learn everything you need to be proficient in Git. 40+ videos, 6 hours of learning, a better understanding of Git.

Get Git Essentials

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:

 



The Pieces of Git

by Ryan Irelan

As far as the Git workflow is concerned, there are three pieces of Git that we should be aware of before moving forward with some slightly more complex (but totally doable!) explanation.

They are:

  • Repository
  • Index
  • Working Tree

Let’s cover each one in a bit more detail.

Repository

A repository is a collection of commits, and a record of what the project’s working tree looked like at one time. You can access the history of commits via the Git log.

There’s always a current starting point in a repository and that’s called the HEAD. A repository also contains tags and branches.

The job of the repository is to be the container that tracks the changes to your project files.

Working Tree

This is a directory on your file system that is associated with a repository.

You can think of this as the filesystem manifestation of the repository. It’s full of the files you edit, where you add new files, and from which you remove unneeded files. Any changes to the Working Tree are noted by the Index (see below), and show up as modified files.

Index

This is a middle area that sits between your Git repository and your Working Tree.

The Index keeps a list of the files Git is tracking and compares them to your Working Tree when you make changes. These changed files show up as modified before you bundle them up into a commit.

You might have heard this called the staging area where changes go before they are committed to the repository as commit objects.

If you ever use the -a flag when committing, then you are effectively bypassing the Index by turning your changes directly into a commit without staging them first.

Learning More About Git

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

Learn more about Git