Moving a tag on a Git branch to a different commit

Today I slipped up when assigning a release tag to a Git repo. After committing my changes and pushing them to GitHub I tagged the HEAD as v1.0.0 and pushed the tags to the remote. Almost immediately I realised that I had forgotten to make a change that I really wanted to be included in that release. Now, the changes had already been pushed to the remote (GitHub in this case) so the sensible and proper thing to do would be to commit my fix and tag it as v1.0.1 but, as this is currently a private repo which only I have access to, I decided to move the tag.
It’s been a while since I’ve done that so it took me a few attempts to remember exactly the steps involved so I thought I’d document them here “just in case”.

If all you’re looking for is the commands, here they are (in these examples I’m assuming the tag to be moved is ‘v1.0.0’). A more detailed explanation follows.

$ git tag -d v1.0.0
$ git push origin :refs/tags/v1.0.0
$ git tag v1.0.0
$ git push origin master --tags

How it works

Firstly, let’s have a look at the state of the repo before running any of these commands

$ git log

* 276ceee (HEAD, master) Fixed spelling.
* 204f97c (tag: v1.0.0, origin/master) Initial commit.

As expected, the tag v1.0.0 is on the initial commit rather than the HEAD, which is where we want it to be.
[Note that I’ve abbreviated the output for clarity].

A quick check of the repo in GitHub confirms that the tag has already been pushed, and is associated with commit 204f97c


The first thing we want to do is delete the v1.0.0 tag from the local repo using git tag -d:

$ git tag -d v1.0.0

Deleted tag 'v1.0.0' (was 204f97c)

$ git log

* 276ceee (HEAD, master) Fixed spelling.
* 204f97c (origin/master) Initial commit.

Then remove it from the remote repo (GitHub):

$ git push origin :refs/tags/v1.0.0

- [deleted] v1.0.0

Then we can assign the tag to the new HEAD:

$ git tag v1.0.0
$ git lg
* 276ceee (HEAD, tag: v1.0.0, master) Fixed spelling.
* 204f97c (origin/master) Initial commit.

and push it to the remote:

$ git push origin master --tags

Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 288 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
204f97c..276ceee master -> master
* [new tag] v1.0.0 -> v1.0.0

Another quick look at GitHub and we can see that the tag is still there but has been moved to the new commit, 276ceee:


Mission accomplished.


Get Grunting

Grunt Logo

For many web developers, Grunt (a.k.a. “Gruntjs”) – “The Javascript Task Runner” – is an essential part of the development workflow. Through automation, tasks such as linting, minifying and unit testing become automatic and part of the edit-save-edit cycle and not chores carried out after code changes are complete.  With its huge collection of plugins, Grunt can significantly cut the time and effort required to build and maintain quality code.

Unfortunately, as the Grunt website itself points out, “While installing grunt is simple, it’s slightly more involved to get it running on your project”. Having spent numerous hours getting my first Grunt task to work, only to think “is that really all that I needed to do?”, I can certainly vouch for the accuracy of that statement. While the official documentation is constantly being improved it still suffers from taking a “too much too soon” approach, leaving the beginner confused and frustrated as he or she wades through the seemingly endless configuration options.

A simple Grunt run: This job runs in the background each time I save a change, linting, minifying and unit testing.
A typical Grunt run: This job runs in the background each time I save a change and lints, minifies and unit tests.

Thankfully there are a number of great articles out there that strip away the complexity and explain just enough to get the new Grunt-er on the right path. Below I’ve listed six tutorials that I found especially useful when getting started with Grunt. Naturally, there is some overlap in their content but they are all concise enough to read and assimilate quickly and each contributes something valuable.

As you’d expect, these are introductory tutorials and don’t cover all aspects of Grunt. As I was specifically interested in using Grunt to run jsLint, UglifyJS for minification and Karma/Jasmine for testing they tend to reflect that.