I ran:
$ git log master
Run Code Online (Sandbox Code Playgroud)
I got:
commit 7940b82568e1d28a76557fbb403c46c3ef3cfe90 (tag: prod-api-2019-04-23, master)
Author: Kent Mills <kent.clark@mwzx.com>
Date: Tue Apr 23 10:33:12 2019 -0700
Run Code Online (Sandbox Code Playgroud)
I am wondering - wrt git tags - does every git tag have a unique commit id associated with it?
For example, if I run git tag how can I see what the commit id's are for those tags? Something like git tag --full or something.
Tags come in one or two parts:
There's a tag name, which is a reference, much like a branch name, except that branch b has full name refs/heads/b while tag t has full name refs/tags/t.
All references store one (1) hash ID. Branch names are constrained to store only commit hash IDs, even though there are four object types: commit, tree, blob, and annotated tag. Tag names are not constrained this way.
If the hash ID stored in the tag reference is the ID of a tag object, the tag object itself stores more data. The data include:
The other Git object here is usually a commit, but that's not a hard and fast requirement: like a tag reference, the tag object can point to another object of any type, even another tag object.
When a tag name points to a tag object, Git calls that an annotated tag. Otherwise, Git calls that reference a lightweight tag.
To turn a reference name into its object, use git rev-parse:
git rev-parse refs/heads/master
git rev-parse refs/tags/v1.2
Run Code Online (Sandbox Code Playgroud)
for instance. By default, git rev-parse finds the target object hash ID and stops there, but you can instruct it to keep going:
The suffix ^{commit} tells git rev-parse that if the object itself is not a commit, but might lead to a commit, keep working. If the object eventually leads to a commit—e.g., if the object is a tag object and its target is another tag object and that second tag object's target is a commit—this "following" process succeeds, and git rev-parse prints the ID of the commit. If the object eventually leads elsewhere—e.g., if the object is a tag object, but the target of this tag object is a blob—the operation fails and git rev-parse prints an error message to stderr, and no hash ID to stdout.
The suffix ^{tree} or ^{blob} tells Git to follow tags or commits to their tree or to a blob. Since every commit object has exactly one tree, the ^{tree} suffix succeeds if the name points to a tag object that points to a commit. It also succeeds if the name points directly to a tree—possible for both lightweight and annotated tags. The ^{blob} suffix can only succeed if the tag points to a blob (directly, as a lightweight tag, or indirectly through some number of tag objects), though, because there's no well-defined way to move from a commit or tree to one particular blob: trees typically hold many blob hash IDs.
The suffix ^{} directs git rev-parse to peel a tag. That is, if the name is a tag name and the first level object is a tag object, Git should follow that object. If the resulting object is another tag object, Git should follow that one as well. Git should repeat this until the tag resolves to any non-tag object—any commit, tree, or blob. Then git rev-parse should produce that non-tag object's hash ID.
Several other Git commands can be told to peel tags, and some do it even without you telling them. For instance, git ls-remote calls up another Git and has the other Git tell your Git about its references—including tag names—and their object hash IDs. When their Git tells your Git about one of their tag names, their Git produces both the top level tag object, if any, and the peeled object hash ID. This shows up as:
<hash1> refs/tags/<tag>
<hash2> refs/tags/<tag>^{}
Run Code Online (Sandbox Code Playgroud)
Here hash1 is the object ID of the annotated tag object, and hash2 is the object ID of the final non-tag object obtained by the peeling process (there must by definition always be such an object).
If you don't see this annotation in git ls-remote output for a tag object, that means their tag is a lightweight tag, pointing directly to the commit, tree, or blob object whose hash ID is listed.
The git for-each-ref command has the * directive to follow tags:
If fieldname is prefixed with an asterisk (
*) and the ref points at a tag object, use the value for the field in the object which the tag object refers to (instead of the field in the tag object).
It's not clear from the documentation whether this fully peels a tag, or just goes one level down: if annotated tag X has as its target the annotated-tag-object of annotated tag Y that has, as Y's target, commit C, does %(*objectname) produce hash Y, or hash C?
| 归档时间: |
|
| 查看次数: |
49 次 |
| 最近记录: |