1. Getting Started
- 1.1 About Version Control
- 1.2 A Short History of Git
- 1.3 What is Git?
- 1.4 The Command Line
- 1.5 Installing Git
- 1.6 First-Time Git Setup
- 1.7 Getting Help
- 1.8 Summary
2. Git Basics
- 2.1 Getting a Git Repository
- 2.2 Recording Changes to the Repository
- 2.3 Viewing the Commit History
- 2.4 Undoing Things
- 2.5 Working with Remotes
- 2.6 Tagging
- 2.7 Git Aliases
- 2.8 Summary
3. Git Branching
- 3.1 Branches in a Nutshell
- 3.2 Basic Branching and Merging
- 3.3 Branch Management
- 3.4 Branching Workflows
- 3.5 Remote Branches
- 3.6 Rebasing
- 3.7 Summary
4. Git on the Server
- 4.1 The Protocols
- 4.2 Getting Git on a Server
- 4.3 Generating Your SSH Public Key
- 4.4 Setting Up the Server
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Third Party Hosted Options
- 4.10 Summary
5. Distributed Git
- 5.1 Distributed Workflows
- 5.2 Contributing to a Project
- 5.3 Maintaining a Project
- 5.4 Summary
7. Git Tools
- 7.1 Revision Selection
- 7.2 Interactive Staging
- 7.3 Stashing and Cleaning
- 7.4 Signing Your Work
- 7.5 Searching
- 7.6 Rewriting History
- 7.7 Reset Demystified
- 7.8 Advanced Merging
- 7.9 Rerere
- 7.10 Debugging with Git
- 7.11 Submodules
- 7.12 Bundling
- 7.13 Replace
- 7.14 Credential Storage
- 7.15 Summary
8. Customizing Git
- 8.1 Git Configuration
- 8.2 Git Attributes
- 8.3 Git Hooks
- 8.4 An Example Git-Enforced Policy
- 8.5 Summary
9. Git and Other Systems
- 9.1 Git as a Client
- 9.2 Migrating to Git
- 9.3 Summary
10. Git Internals
- 10.1 Plumbing and Porcelain
- 10.2 Git Objects
- 10.3 Git References
- 10.4 Packfiles
- 10.5 The Refspec
- 10.6 Transfer Protocols
- 10.7 Maintenance and Data Recovery
- 10.8 Environment Variables
- 10.9 Summary
A1. Appendix A: Git in Other Environments
- A1.1 Graphical Interfaces
- A1.2 Git in Visual Studio
- A1.3 Git in Visual Studio Code
- A1.4 Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git in Sublime Text
- A1.6 Git in Bash
- A1.7 Git in Zsh
- A1.8 Git in PowerShell
- A1.9 Summary
A2. Appendix B: Embedding Git in your Applications
- A2.1 Command-line Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
A3. Appendix C: Git Commands
- A3.1 Setup and Config
- A3.2 Getting and Creating Projects
- A3.3 Basic Snapshotting
- A3.4 Branching and Merging
- A3.5 Sharing and Updating Projects
- A3.6 Inspection and Comparison
- A3.7 Debugging
- A3.8 Patching
- A3.9 Email
- A3.10 External Systems
- A3.11 Administration
- A3.12 Plumbing Commands
2.6 Git Basics - Tagging
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 (
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.
Listing Your Tags
Listing the existing tags in Git is straightforward.
git tag (with optional
$ git tag v1.0 v2.0
This command lists the tags in alphabetical order; the order in which they are displayed has no real importance.
You can also search for tags that match a particular pattern. The Git source repo, for instance, contains more than 500 tags. If you’re interested only in looking at the 1.8.5 series, you can run this:
$ git tag -l "v1.8.5*" v1.8.5 v1.8.5-rc0 v1.8.5-rc1 v1.8.5-rc2 v1.8.5-rc3 v18.104.22.168 v22.214.171.124 v126.96.36.199 v188.8.131.52 v184.108.40.206
Listing tag wildcards requires
If you want just the entire list of tags, running the command
If, however, you’re supplying a wildcard pattern to match tag names, the use of
Git supports two types of tags: lightweight and annotated.
A lightweight tag is very much like a branch that doesn’t change — it’s just a pointer to a specific commit.
Annotated tags, however, are stored as full objects in the Git database. They’re checksummed; contain the tagger name, email, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG). It’s generally recommended that you create annotated tags so you can have all this information; but if you want a temporary tag or for some reason don’t want to keep the other information, lightweight tags are available too.
Creating an annotated tag in Git is simple.
The easiest way is to specify
-a when you run the
$ git tag -a v1.4 -m "my version 1.4" $ git tag v0.1 v1.3 v1.4
-m specifies a tagging message, which is stored with the tag.
If you don’t specify a message for an annotated tag, Git launches your editor so you can type it in.
You can see the tag data along with the commit that was tagged by using the
git show command:
$ git show v1.4 tag v1.4 Tagger: Ben Straub <email@example.com> Date: Sat May 3 20:19:12 2014 -0700 my version 1.4 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <firstname.lastname@example.org> Date: Mon Mar 17 21:52:11 2008 -0700 Change version number
That shows the tagger information, the date the commit was tagged, and the annotation message before showing the commit information.
Another way to tag commits is with a lightweight tag.
This is basically the commit checksum stored in a file — no other information is kept.
To create a lightweight tag, don’t supply any of the
-m options, just provide a tag name:
$ git tag v1.4-lw $ git tag v0.1 v1.3 v1.4 v1.4-lw v1.5
This time, if you run
git show on the tag, you don’t see the extra tag information.
The command just shows the commit:
$ git show v1.4-lw commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <email@example.com> Date: Mon Mar 17 21:52:11 2008 -0700 Change version number
You can also tag commits after you’ve moved past them. Suppose your commit history looks like this:
$ git log --pretty=oneline 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment' a6b4c97498bd301d84096da251c98a07c7723e65 Create write support 0d52aaab4479697da7686c15f77a3d64d9165190 One more thing 6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment' 0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc Add commit function 4682c3261057305bdd616e23b64b0857d832627b Add todo file 166ae0c4d3f420721acbb115cc33848dfcc2121a Create write support 9fceb02d0ae598e95dc970b74767f19372d61af8 Update rakefile 964f16d36dfccde844893cac5b347e7b3d44abbc Commit the todo 8a5cbc430f1a9c3d00faaeffd07798508422908a Update readme
Now, suppose you forgot to tag the project at v1.2, which was at the “Update rakefile” commit. You can add it after the fact. To tag that commit, you specify the commit checksum (or part of it) at the end of the command:
$ git tag -a v1.2 9fceb02
You can see that you’ve tagged the commit:
$ git tag v0.1 v1.2 v1.3 v1.4 v1.4-lw v1.5 $ git show v1.2 tag v1.2 Tagger: Scott Chacon <firstname.lastname@example.org> Date: Mon Feb 9 15:32:16 2009 -0800 version 1.2 commit 9fceb02d0ae598e95dc970b74767f19372d61af8 Author: Magnus Chacon <email@example.com> Date: Sun Apr 27 20:43:35 2008 -0700 Update rakefile ...
By default, the
git push command doesn’t transfer tags to remote servers.
You will have to explicitly push tags to a shared server after you have created them.
This process is just like sharing remote branches — you can run
git push origin <tagname>.
$ git push origin v1.5 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 firstname.lastname@example.org:schacon/simplegit.git * [new tag] v1.5 -> v1.5
If you have a lot of tags that you want to push up at once, you can also use the
--tags option to the
git push command.
This will transfer all of your tags to the remote server that are not already there.
$ git push origin --tags Counting objects: 1, done. Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) To email@example.com:schacon/simplegit.git * [new tag] v1.4 -> v1.4 * [new tag] v1.4-lw -> v1.4-lw
Now, when someone else clones or pulls from your repository, they will get all your tags as well.
To delete a tag on your local repository, you can use
git tag -d <tagname>.
For example, we could remove our lightweight tag above as follows:
$ git tag -d v1.4-lw Deleted tag 'v1.4-lw' (was e7d5add)
Note that this does not remove the tag from any remote servers. There are two common variations for deleting a tag from a remote server.
The first variation is
git push <remote> :refs/tags/<tagname>:
$ git push origin :refs/tags/v1.4-lw To /firstname.lastname@example.org:schacon/simplegit.git - [deleted] v1.4-lw
The way to interpret the above is to read it as the null value before the colon is being pushed to the remote tag name, effectively deleting it.
The second (and more intuitive) way to delete a remote tag is with:
$ git push origin --delete <tagname>
Checking out Tags
If you want to view the versions of files a tag is pointing to, you can do a
git checkout of that tag, although this puts your repository in “detached HEAD” state, which has some ill side effects:
$ git checkout v2.0.0 Note: switching to 'v2.0.0'. 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 -c with the switch command. Example: git switch -c <new-branch-name> Or undo this operation with: git switch - Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at 99ada87... Merge pull request #89 from schacon/appendix-final $ git checkout v2.0-beta-0.1 Previous HEAD position was 99ada87... Merge pull request #89 from schacon/appendix-final HEAD is now at df3f601... Add atlas.json and cover image
In “detached HEAD” state, if you make changes and then create a commit, the tag will stay the same, but your new commit won’t belong to any branch and will be unreachable, except by the exact commit hash. Thus, if you need to make changes — say you’re fixing a bug on an older version, for instance — you will generally want to create a branch:
$ git checkout -b version2 v2.0.0 Switched to a new branch 'version2'
If you do this and make a commit, your
version2 branch will be slightly different than your
v2.0.0 tag since it will move forward with your new changes, so do be careful.