2021-08-31
|~11 min read
|2010 words
I was recently trying to publish a new version our product when I ran into an issue: the tag already existed and so my command exited with a failure.
This got me wondering what exactly are Git Tags, why do we use them, and how might I get better at using them. The purpose of this page is to answer those questions (and be slightly more concise than the excellent primary source: the Git Handbook’s section on tagging).
The second (and more intuitive) way to delete a remote tag is with:
$ git push origin --delete <tagname>
Let’s start by addressing some fundamental questions: What are tags? How are they (typically) used? Why might we care?
From the Handbook:
Like most VCSs, Git has the ability to tag specific points in a repository’s history as being important. Typically, people use this functionality to mark release points (v1.0, v2.0 and so on). In this section, you’ll learn how to list existing tags, how to create and delete tags, and what the different types of tags are.
Tags then are landmarks. They make identifying points in a product’s history straightforward. The most common use is for releases - particularly useful for rollbacks.A lot of CI/CD tooling can be configured to use tags.
Now that we know why we might want to create a tag, the natural next step is to actually do that.
The easiest way to create a tag is with the git command from within a git managed directory:
% git tag vx.yy.zz
This will create a tag for the most recent commit.
% g l
* 0675a9c1 2021-08-30 | Add feature x (HEAD -> main, tag: vx.yy.zz, origin/main) [Stephen]
| major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id
Yarn has a slightly different API using flags instead of arguments to direct the new version.
% yarn version --help
Usage: yarn [command] [flags]
Update the version of your package via the command line.
Options:
-v, --version output the version number
--no-default-rc prevent Yarn from automatically detecting yarnrc and npmrc files
--use-yarnrc <path> specifies a yarnrc file that Yarn should use (.yarnrc only, not .npmrc) (default: )
--verbose output verbose messages on internal operations
--offline trigger an error if any required dependencies are not available in local cache
--prefer-offline use network only if dependencies are not available in local cache
--enable-pnp, --pnp enable the Plug'n'Play installation
--disable-pnp disable the Plug'n'Play installation
--strict-semver
--json format Yarn log messages as lines of JSON (see jsonlines.org)
--ignore-scripts don't run lifecycle scripts
--har save HAR output of network traffic
--ignore-platform ignore platform checks
--ignore-engines ignore engines check
--ignore-optional ignore optional dependencies
--force install and build packages even if they were built before, overwrite lockfile
--skip-integrity-check run install without checking if node_modules is installed
--check-files install will verify file tree of packages for consistency
--no-bin-links don't generate bin links when setting up packages
--flat only allow one version of a package
--prod, --production [prod]
--no-lockfile don't read or generate a lockfile
--pure-lockfile don't generate a lockfile
--frozen-lockfile don't generate a lockfile and fail if an update is needed
--update-checksums update package checksums from current repository
--link-duplicates create hardlinks to the repeated modules in node_modules
--link-folder <path> specify a custom folder to store global links
--global-folder <path> specify a custom folder to store global packages
--modules-folder <path> rather than installing modules into the node_modules folder relative to the cwd, output them here
--preferred-cache-folder <path> specify a custom folder to store the yarn cache if possible
--cache-folder <path> specify a custom folder that must be used to store the yarn cache
--mutex <type>[:specifier] use a mutex to ensure only one yarn instance is executing
--emoji [bool] enable emoji in output (default: true)
-s, --silent skip Yarn console logs, other types of logs (script output) will be printed
--cwd <cwd> working directory to use (default: /Users/stephen.weiss/code/digital-garden)
--proxy <host>
--https-proxy <host>
--registry <url> override configuration registry
--no-progress disable progress bar
--network-concurrency <number> maximum number of concurrent network requests
--network-timeout <milliseconds> TCP timeout for network requests
--non-interactive do not show interactive prompts
--scripts-prepend-node-path [bool] prepend the node executable dir to the PATH in scripts
--no-node-version-check do not warn when using a potentially unsupported Node version
--focus Focus on a single workspace by installing remote copies of its sibling workspaces.
--otp <otpcode> one-time password for two factor authentication
--new-version [version] new version
--major auto-increment major version number
--minor auto-increment minor version number
--patch auto-increment patch version number
--premajor auto-increment premajor version number
--preminor auto-increment preminor version number
--prepatch auto-increment prepatch version number
--prerelease auto-increment prerelease version number
--preid [preid] add a custom identifier to the prerelease
--message [message] message
--no-git-tag-version no git tag version
--no-commit-hooks bypass git hooks when committing new version
-h, --help output usage information
Visit https://yarnpkg.com/en/docs/cli/version for documentation about this command.
By default, tags are not pushed when you push to a remote repository.
To ensure that tags are published to a remote we need to explicitly push them:
% git push origin --tags
To see all of the existing tags we can use:
% git tag --list
v0.1.0
v0.2.0
v0.3.0
To delete a tag (locally):
% git tag --delete v0.3.0
Deleted tag 'v0.3.0'
If the tags have been pushed to a remote repository already:
% git push origin --delete v0.3.0
GIT-TAG(1) Git Manual GIT-TAG(1)
NAME
git-tag - Create, list, delete or verify a tag object signed with GPG
SYNOPSIS
git tag [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] [-e]
<tagname> [<commit> | <object>]
git tag -d <tagname>...
git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
[--points-at <object>] [--column[=<options>] | --no-column]
[--create-reflog] [--sort=<key>] [--format=<format>]
[--[no-]merged [<commit>]] [<pattern>...]
git tag -v [--format=<format>] <tagname>...
DESCRIPTION
Add a tag reference in refs/tags/, unless -d/-l/-v is given to delete, list or verify tags.
Unless -f is given, the named tag must not yet exist.
If one of -a, -s, or -u <keyid> is passed, the command creates a tag object, and requires a tag message. Unless -m <msg> or
-F <file> is given, an editor is started for the user to type in the tag message.
If -m <msg> or -F <file> is given and -a, -s, and -u <keyid> are absent, -a is implied.
Otherwise, a tag reference that points directly at the given object (i.e., a lightweight tag) is created.
A GnuPG signed tag object will be created when -s or -u <keyid> is used. When -u <keyid> is not used, the committer identity
for the current user is used to find the GnuPG key for signing. The configuration variable gpg.program is used to specify
custom GnuPG binary.
Tag objects (created with -a, -s, or -u) are called "annotated" tags; they contain a creation date, the tagger name and
e-mail, a tagging message, and an optional GnuPG signature. Whereas a "lightweight" tag is simply a name for an object
(usually a commit object).
Annotated tags are meant for release while lightweight tags are meant for private or temporary object labels. For this
reason, some git commands for naming objects (like git describe) will ignore lightweight tags by default.
OPTIONS
-a, --annotate
Make an unsigned, annotated tag object
-s, --sign
Make a GPG-signed tag, using the default e-mail address's key. The default behavior of tag GPG-signing is controlled by
tag.gpgSign configuration variable if it exists, or disabled oder otherwise. See git-config(1).
--no-sign
Override tag.gpgSign configuration variable that is set to force each and every tag to be signed.
-u <keyid>, --local-user=<keyid>
Make a GPG-signed tag, using the given key.
-f, --force
Replace an existing tag with the given name (instead of failing)
-d, --delete
Delete existing tags with the given names.
-v, --verify
Verify the GPG signature of the given tag names.
-n<num>
<num> specifies how many lines from the annotation, if any, are printed when using -l. Implies --list.
The default is not to print any annotation lines. If no number is given to -n, only the first line is printed. If the
tag is not annotated, the commit message is displayed instead.
-l, --list
List tags. With optional <pattern>..., e.g. git tag --list 'v-*', list only the tags that match the pattern(s).
Running "git tag" without arguments also lists all tags. The pattern is a shell wildcard (i.e., matched using
fnmatch(3)). Multiple patterns may be given; if any of them matches, the tag is shown.
This option is implicitly supplied if any other list-like option such as --contains is provided. See the documentation
for each of those options for details.
--sort=<key>
Sort based on the key given. Prefix - to sort in descending order of the value. You may use the --sort=<key> option
multiple times, in which case the last key becomes the primary key. Also supports "version:refname" or "v:refname" (tag
names are treated as versions). The "version:refname" sort order can also be affected by the "versionsort.suffix"
configuration variable. The keys supported are the same as those in git for-each-ref. Sort order defaults to the value
configured for the tag.sort variable if it exists, or lexicographic order otherwise. See git-config(1).
--color[=<when>]
Respect any colors specified in the --format option. The <when> field must be one of always, never, or auto (if <when>
is absent, behave as if always was given).
-i, --ignore-case
Sorting and filtering tags are case insensitive.
--column[=<options>], --no-column
Display tag listing in columns. See configuration variable column.tag for option syntax.--column and --no-column without
options are equivalent to always and never respectively.
This option is only applicable when listing tags without annotation lines.
--contains [<commit>]
Only list tags which contain the specified commit (HEAD if not specified). Implies --list.
--no-contains [<commit>]
Only list tags which don't contain the specified commit (HEAD if not specified). Implies --list.
--merged [<commit>]
Only list tags whose commits are reachable from the specified commit (HEAD if not specified), incompatible with
--no-merged.
--no-merged [<commit>]
Only list tags whose commits are not reachable from the specified commit (HEAD if not specified), incompatible with
--merged.
--points-at <object>
Only list tags of the given object (HEAD if not specified). Implies --list.
-m <msg>, --message=<msg>
Use the given tag message (instead of prompting). If multiple -m options are given, their values are concatenated as
separate paragraphs. Implies -a if none of -a, -s, or -u <keyid> is given.
-F <file>, --file=<file>
Take the tag message from the given file. Use - to read the message from the standard input. Implies -a if none of -a,
-s, or -u <keyid> is given.
-e, --edit
The message taken from file with -F and command line with -m are usually used as the tag message unmodified. This option
lets you further edit the message taken from these sources.
--cleanup=<mode>
This option sets how the tag message is cleaned up. The <mode> can be one of verbatim, whitespace and strip. The strip
mode is default. The verbatim mode does not change message at all, whitespace removes just leading/trailing whitespace
lines and strip removes both whitespace and commentary.
--create-reflog
Create a reflog for the tag. To globally enable reflogs for tags, see core.logAllRefUpdates in git-config(1). The
negated form --no-create-reflog only overrides an earlier --create-reflog, but currently does not negate the setting of
core.logAllRefUpdates.
--format=<format>
A string that interpolates %(fieldname) from a tag ref being shown and the object it points at. The format is the same
as that of git-for-each-ref(1). When unspecified, defaults to %(refname:strip=2).
<tagname>
The name of the tag to create, delete, or describe. The new tag name must pass all checks defined by git-check-ref-
format(1). Some of these checks may restrict the characters allowed in a tag name.
<commit>, <object>
The object that the new tag will refer to, usually a commit. Defaults to HEAD.
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!