loading...
Cover image for Using Git Tags To Version Coding Tutorials

Using Git Tags To Version Coding Tutorials

emmabostian profile image Emma Bostian ✨ ・8 min read

Coding tutorials can be difficult to structure. It’s often so easy to get caught up in your expanding code base and keep track of important project milestones. Wouldn’t it be great if there was a solution?

Look no further! Git tags to the rescue!

Git tags are a great way to version your coding tutorials to make your life, and your readers’ lives, easier. They allow you to tag specific points in a repository’s history and return to them at later points in time.

First, let’s check out the basics of creating, listing, checking out, and deleting tags.

List Existing Tags

Listing your Git tags is as simple as typing git tag followed by an optional -l or --list parameter. This command will list all tags in alphabetical order.

Additionally, you can list all tags which match a certain structure. For example, if I want to list all tags that begin with v12, I can type git tag -l "v12.*" and this might output something like this:

$ git tag -l "v12.*"
v12.0.0
v12.0.1
v12.1.0
v12.3

Note: If you want to use the wildcard (*) to match specific tag patterns, you must include the --list (or -l) parameter.

Creating A Tag

You can create two types of tags: lightweight and annotated.

Lightweight Tags

A lightweight tag is similar to a branch; it’s just a pointer to a specific commit.

To create a lightweight tag, all you need to provide is a tag name. You don’t need to include any of the flags you would see with annotated tags (see below).

$ git tag v2.4-lightweight
$ git tag
v0.1
v0.5
v2.3
v2.4-lightweight

If we run git show on this tag, we simply see the commit hash, the author, the date, and the commit message.

$ git show v2.4-lightweight
commit ca82a6dff817ec66f44342007202690a93763949
Author: Emma Wedekind <wedekind.emma@gmail.com>
Date: Sat Mar 16 09:48:93 2918 -0700

        changed the version number

Annotated Tags

An annotated tag, in contrast, is stored as a full object in the Git database. These tags are checksummed; they contain the name of the person who created the tag, email, and date. Annotated tags include a message and can be verified with a GNU Privacy Guard (GPG).

To create an annotated flag, you can use the -a flag.

$ git tag -a v2.4 -m "This is my 2.4 version"
$ git tag
v0.1
v0.5
v2.3
v2.4

The -m flag is followed by the tagging message you want to include. If you don’t include this flag, Git will launch your code editor for you to include it.

We can use the git show command to view the tag data.

$ git show v2.4
tag v2.4
Tagger: Emma Wedekind <wedekind.emma@gmail.com>
Date: Sat Mar 16 09:48:93 2918 -0700

This is my 2.4 version

commit ca82a6dff817ec66f44342007202690a93763949
Author: Kai Wedekind <wedekind.kai@gmail.com>
Date: Thursday Mar 14 19:38:11 2918 -0700

           changed the version number

Pushing Tags To Remote Servers

Using the git push command won’t push the tags you’ve created; you must explicitly push each tag after they’ve been created. This process is similar to sharing remote branches.

$ git push origin v2.4
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To git@github.com:emmawedekind/mycoolproject.git
 * [new tag]         v2.4 -> v2.4

To push multiple tags, you can use the --tags option to the push command.

$ git push origin --tags

Deleting Tags

You can use the git tag -d <tagname> command to delete a tag from your local repository.

$ git tag -d v2.4-lightweight
Deleted tag 'v2.4-leightweight' (was e7d6add)

This command, however, doesn’t remove the tag from your remote servers. To complete this action you can either use the git push <remote> :refs/tags/<tagname> command:

$ git push origin :refs/tags/v2.4-lightweight
To /git@github.com:emmawedekind/mycoolproject.git
 - [deleted]         v2.4-lightweight

You can additionally use the git push origin --delete <tagname> command:

$ git push origin --delete v2.4-lightweight

Checking Out Tags

To check out a tag, you can use the git checkout command.

$ git checkout v2.4-lightweight
Note: checking out 'v2.4-lightweight'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch>

HEAD is now at 99ada87... Merge pull request #89 from emmawedekind/readme-addition

$ git checkout 2.0-beta-0.1
Previous HEAD position was 99ada87... Merge pull request #89 from emmawedekind/readme-addition
HEAD is now at df3f601... add getting started info

Great! Now that we know the basics of tagging, let’s use it to version one of our coding tutorials.

Project Structure

Let’s suppose I’m creating a tutorial called “Web Development For Beginners.” This tutorial will have three milestones: HTML, CSS, and JavaScript.

In order to preserve my project history at each milestone, and be able to quickly switch between the different histories, I want to create three tags: html, css, js.

Milestone 1: HTML

  1. Create a GitHub repository where you will keep your coding tutorial code. You can find my code here.

GitHub repo

  1. Clone the repository.

Terminal

  1. Add an HTML template with some elements.

HTML

  1. Now, let’s add and commit our HTML code.
$ git add index.html
$ git commit -m "Adding the HTML structure"
  1. Next, let’s add a tag to our HTML milestone so we can re-visit this code in the future. In the terminal, type the following command:
git tag -a html -m "The HTML code for this project"

Note: You must commit your code before creating the tag.

Now, when you run git tag, you should see the name of your tag.

Terminal

  1. We need to push the code and the tag to the remote server. Remember that tags aren’t included in the git push command; we have to use the git push <origin> <tagname> command.

Let’s push our code first.

$ git push

Great! If we head back to GitHub, we can see our code has been pushed to master.

GitHub

Now, let’s push our tag name to GitHub.

$ git push origin html

Once this completes, let’s refresh GitHub once more. Now, we should see the tag appear under the Releases tab.

GitHub

GitHub

Wonderful! Now let’s create our next two milestones: CSS and JavaScript!

Milestone 2: CSS

The process for tagging the CSS milestone will be identical to the steps we followed for milestone 1. So for brevity’s sake, I’ll quickly run through the process.

  1. Create a stylesheet. I’ll call mine styles.css.
  2. Add some styling to the page. You can use class names, but to keep my tutorial short, I will just style the base HTML elements. Additionally, I added a <section> element to wrap the main content so I could style it appropriately. You can view the full code here.
  3. Link the stylesheet in the head of the index.html file
<link rel="stylesheet" href="./styles.css">
  1. Add and commit your code. You can refer to step four in milestone one for more details.

  2. Now it’s time to tag!

$ git tag -a css -m "The CSS code for this project"

Now when we run git tag, we should see two tags: html and css.

Terminal

  1. Push your code and your tag to GitHub
$ git push
$ git push origin css
  1. Double check that your tag and your code have been successfully pushed to the repository.

GitHub

Finally, let’s add some behavior!

Milestone 3: JavaScript

I’m going to keep things super simple; we’ll add a button that, when clicked, alerts the user that they’ve clicked the button.

For the sake of not repeating myself, I’m going to skip the steps we followed in milestones one and two. But here’s a quick overview of the coded changes I made:

  • Create an index.js file.
  • Link the index.js file in my index.html file.
  • Add a <button> element to the template.
  • Attach an event listener to the button which will trigger an alert when clicked.
  • Add some styling to the button.
  • Add and commit your code.
  • Create the js tag.
  • Push all code and the tag to the GitHub repository.

And just to double check everything was pushed to the repository…

GitHub

Great! Now let’s learn how to check out the different branches to view the milestone code.

Checking Out Milestones

During your coding tutorial, you may want to reference specific snapshots of code. For example, if I’m referencing the code I wrote in the HTML milestone, I want to instruct students to check out the html tag. You can do this in the following way:

$ git checkout html

Your terminal output should look something like the following.

Terminal

And when we refresh the browser, you should see the code without any styling or behavior.

HTML

Now, let’s check out the CSS tag with git checkout css. Refreshing the browser, we see the following.

CSS

And lastly let’s check the JavaScript with git checkout js.

JS

JS

Great! It’s all working as expected!

Viewing Milestones In GitHub

It’s also possible to view the milestones within GitHub. Simply click the Switch Branches drop down, and select tags.

GitHub

Now, you can select the tag you want to view the code for.

GitHub


It’s as simple as that! I hope this tutorial proved useful and gave you the skills you need to create tags in your coding tutorials.

Discussion

pic
Editor guide
Collapse
juliang profile image
Julian Garamendy

Thanks for this! I didn't know the difference between lightweight and annotated tags.

I also use tags when trying to identify when a bug was introduced. I normally create "before-x", "after-x" tags to quickly jump between commits without accidentally checking out the wrong thing (which would add even more confusion)

Collapse
xexyl profile image
xexzy

For debugging you should really look into git bisect.

Maybe it’s not a good way for you but it’s specially useful and iirc designed for debugging/finding which commit introduced the bugs you’re looking for.

Collapse
juliang profile image
Julian Garamendy

Awesome! Thanks! I didn't know about git bisect either!

Thread Thread
xexyl profile image
xexzy

No problem mate!

I have seen some really interesting articles on it but I am not sure where exactly. I think I could find it if I were to bother but I have actually never used it as I have always used my own system. Even so it’s good to have alternative methods for things and if nothing else it’s something new to learn and by extension come up with new ideas and so on.

It should be remembered too that you can use it for more than just finding a commit a bug was introduced. In the end binary searching is a valuable tool and you can use similar systems for making decisions irl by taking a list of things and breaking them into the keep pile until you finally have two left.

Anyway glad to have offered something useful!

Cheers.

Collapse
andychiare profile image
Collapse
jfn0 profile image
jfn0

Didnt know a bout git tutor, thank!

Collapse
jankeromnes profile image
Jan Keromnes

That's really smart! Many thanks for this helpful write-up.

We also tried to address this with gitpod.io snapshots, which allow you to capture and share the full state of a workspace with a URL (see ssloy's awesome 3D tutorials using snapshots for each step: github.com/ssloy/tinyraycaster/wik... ).

But today I learned that you can also do it with tags. Thanks again!

Collapse
seankilleen profile image
Sean Killeen

Thanks for the article!

I've been going back and forth on my approach and I wonder if you have a preference.

Would you prefer:

  • Making these commits along the master branch and tagging? In this case, when folks first pull the repository, they'll be looking at the final version.
  • Making these commits in branches off of each other (e.g. step-02 is tagged to the latest in a branch that is created off of step-01 which was created off of step-00). This seems like it could be more complex to maintain, but results in those taking the tutorial pulling down the "before" version at first.

Not sure which way to go, and wasn't sure if you or other readers here might have some preferences.

Thanks again!

Collapse
learnbyexample profile image
Sundeep

very nicely presented and explained, am gonna try on my repos

one question, is it possible to add tags to a particular commit in history?

Collapse
emmabostian profile image
Emma Bostian ✨ Author

I'm not sure, you'd have to check the official documentation :)

Collapse
xexyl profile image
xexzy

Yes. Yes you can. See the following for example :

stackoverflow.com/questions/440417...

Collapse
learnbyexample profile image
Sundeep

cool, thanks for the link, exactly what I was looking for :)

Thread Thread
xexyl profile image
xexzy

Welcome mate!

Collapse
mikeborn profile image
Michael Born

Pretty cool! I've been writing some CF tutorials recently, and I briefly wondered "Hmm, would Git tagging make this way easier to switch between examples?" Because otherwise you either give the student/reader the Full Working Code, or nothing at all.

Thank you! I'll give tags another shot.

Collapse
geefygeorge profile image
David Salter

Great article and fantastic technique to help others learn. :)

Collapse
lokidev profile image
LokiDev

As always: Very useful. I knew about tags and used it very poorly. This article gave more insight (I didn't knew the difference between lightweight and annotated tags before)

Collapse
xrr2016 profile image
xiaoranran1993

good article!

Collapse
thomascraig profile image
Thomas Craig

Great post as we are currently going thru this exercise for a current project and this is helpful.

Collapse
giovannicodes profile image
Giovanni Cortés

I am doing a monogame tutorial and I using branches instead. Is very useful

Collapse
jsjoeio profile image
Joe Previte (he/him)

Genius idea! Thank you for sharing!

Collapse
emmabostian profile image
Collapse
wiltel492019 profile image
Wiltel492019

Milestones great.

Collapse
jnario profile image
Jose Nario

Not sure why I always neglect tags, but clearly I'm missing out. Thanks for the inspiration.