Home > other >  simple ref vs lightweight tags in git
simple ref vs lightweight tags in git

Time:12-16

i'm currently try to understand internal of git; my question is what is the difference between a lightweight tag and a simple ref ? based on what i've read so far, a lightweight tag is actually a file with name of the tag and its content is an object-id [a commit-object id i guess?].in this book 'git pocket guide', the author said "a simple ref points directly to an object-id"; that's where i'm confused! in my opinion these are same things but named differently. is it correct to say that a lightweight-tag is a specific version of a simple ref? because lightweight tag only can points to commit-objects but simple ref isn't limited to commits only.

CodePudding user response:

A ref (or the longer variant, reference ) is a name, in Git. There are many forms of references:

  • refs/heads/xyz is the branch name xyz;
  • refs/tags/xyz is the tag name xyz;
  • refs/remotes/origin/xyz is the remote-tracking name that your Git is using for a branch named xyz as seen in some other Git repository you're calling origin;

and so on.

A Git object is one of four object types:

  • a blob object holds data (file contents or the target of a symbolic link, for instance);
  • a tree object holds <mode, name, hash> tuples in it, where the mode tells you what kind of Git object the hash specifies and the name contains a name component (directory or file name);
  • a commit object holds the metadata of a commit, which must contain specific headers (including exactly one tree line giving the hash ID of one tree object: this is the commit's snapshot); and
  • a tag object or annotated tag object contains the tag data, which—like a commit—must contain specific headers, including an object line giving the hash ID of the tagged object (which may be any of the four object types, including another annotated tag).

All objects have a unique hash ID. This hash ID acts as the key in a simple key-value database. Git will use the key to find the object; you must provide the key (somehow). If you provide a shortened key—i.e., a prefix of a key—Git will look up all objects found by that prefix; if only one is found, that's assumed to be the correct full hash ID, and we proceed from there; if more than one is found, we have an ambiguous hash ID (it could be any of those).

All refs must contain the hash ID of some existing, valid object. Some objects also contain hash IDs; these too must be hash IDs of some existing, valid object.1

Some refs are constrained as to which object types they may contain: in particular, branch names must contain commit hash IDs. Since a remote-tracking name is created by reading a branch name from some other Git repository (which should obey this same set of constraints), a remote-tracking name should also contain a commit hash ID. Tag names, however, can contain the hash ID of any of the four internal object types.

A lightweight tag is a ref of the form refs/tags/*—hence a tag name—that contains a valid hash ID, but one that is for an internal Git object that is not an tag object. An annotated tag is a ref of the form refs/tags/* that contains a valid hash ID for an object that is an annotated tag object.

is it correct to say that a lightweight-tag is a specific version of a simple ref?

Mostly, yes. A lightweight tag is a specific ref: one that starts with refs/tags (and then a slash and more name characters). However, it meets one more constraint: the hash ID stored in that ref is that of an object whose types is not "annotated tag".


1This constraint is relaxed a bit in a so-called shallow or partial clone. (You can have a clone that is both shallow and partial.) The hash ID should be valid, but we can't tell whether it is until we fill in the missing objects.

CodePudding user response:

You are right : a lightweight tag is a simple ref.

Its main specificity is that it is stored under .git/refs/tags, and that's a convention which indicates that git commands can treat it like a tag :

  • git tag --list will list it,
  • git tag -d <tag_name> will delete it,
  • git will shorten the name refs/tags/tag_name to tag_name in several cases,
  • etc ...

The other main conventions related to refs are :

  • branches are stored under refs/heads
  • remote references (or remote branches) are stored under refs/remotes/<remote_name>/

and these references are simple refs too.


An example of a non simple ref is HEAD (stored in .git/HEAD).

You can run cat .git/HEAD to view its content : if you currently are on a branch, you should see somthing like :

$ cat .git/HEAD
ref: refs/heads/my_branch

This is called a symbolic ref, and commands that act on HEAD (for example : git log HEAD) will "translate" HEAD to my_branch.

  • Related