So, I want all the tags to be bound to the current commit. What is the best way to do this? Iterate through all the tags and see if there is tag.Target.Sha == commit.Sha ? This is not good. Is there another way?
There are two things to consider when it comes to tags.
- A tag can point to something else besides Commit (for example, Tree or Blob).
- A tag can point to another tag (anchored annotated tags)
The code below should suit your needs, taking these points into account.
Note. repo.Commits will list only the amounts reachable from the current branch ( HEAD ). The code below extends this to easily view all available targets.
... using (var repo = new Repository("Path/to/your/repo")) { // Build up a cached dictionary of all the tags that point to a commit var dic = TagsPerPeeledCommitId(repo); // Let enumerate all the reachable commits (similarly to `git log --all`) foreach (Commit commit in repo.Commits.QueryBy(new CommitFilter {Since = repo.Refs})) { foreach (var tags in AssignedTags(commit, dic)) { Console.WriteLine("Tag {0} points at {1}", tags.Name, commit.Id); } } } .... private static IEnumerable<Tag> AssignedTags(Commit commit, Dictionary<ObjectId, List<Tag>> tags) { if (!tags.ContainsKey(commit.Id)) { return Enumerable.Empty<Tag>(); } return tags[commit.Id]; } private static Dictionary<ObjectId, List<Tag>> TagsPerPeeledCommitId(Repository repo) { var tagsPerPeeledCommitId = new Dictionary<ObjectId, List<Tag>>(); foreach (Tag tag in repo.Tags) { GitObject peeledTarget = tag.PeeledTarget; if (!(peeledTarget is Commit)) { // We're not interested by Tags pointing at Blobs or Trees continue; } ObjectId commitId = peeledTarget.Id; if (!tagsPerPeeledCommitId.ContainsKey(commitId)) { // A Commit may be pointed at by more than one Tag tagsPerPeeledCommitId.Add(commitId, new List<Tag>()); } tagsPerPeeledCommitId[commitId].Add(tag); } return tagsPerPeeledCommitId; }
source share