How do you enabled Limited Refs in TFS Git?

Viewed 404

In their articles about Git at scale, Microsoft mention this blog post which talks about a concept called "Limited Refs". It appears to be an extremely useful feature for limiting which server branches are visible to each user to allow a more organized client experience in a non-fork based TFS Git server configuration.

Unfortunately, the article neglected to mention how to use said feature and no other information I can find online seems to document it. I've done a bunch of digging on my own and discovered the prc_UpdateGitLimitedRefCriteria stored procedure in the TFS SQL DB that adds records to a table to apply filters to the refs returned to a client, however adding information to that table is not sufficient by itself. There must be some on/off switch which I've been unable to locate.

Has anyone had any luck getting the Limited Refs functionality to be enabled and if so, how do you do it?

2 Answers

So after some extensive poking around the DB, I have managed to hack together a solution. I couldn't find a way to do it through the UI, but there are two key things that have to be done in the DB to make it work.

First, you need to enable the feature, which is enabled in the repository settings. While I couldn't find a setting in the UI, if you adjust anything from the default settings on the repo, a JSON object is saved to the dbo.tbl_PolicyConfigurationRevision table which includes an "optimizedByDefault" element which will be null, change it from null to true and the feature will now be enabled on the repo in question.

Alternately, this can be accomplished using the Policy Configuration endpoint for the TFS Rest API as described here. It's a bit more involved and still involves tweaking the JSON, but it goes through officially exposed channels without requiring direct DB manipulation and will properly version the configuration change.

Second, you need to specify what the "important" refs are. There is a stored proc and a custom data type to help with this. dbo.prc_UpdateGitLimitedRefCriteria takes the partitionId, dataspaceId, repositoryId and two custom table data type records for the exactRefs matches and the namespaceRefs matches. Build up the tables with your important refs in them and call the stored proc to add them to the list.

It appears that this ends up going through the prc_QueryGitRefs stored proc for filtering the refs, so you can look in there if you need more detail about how to format them so that processing works correctly.

After a bit more experimentation, it appears that there is an undocumented API endpoint for limitedRefCriteria as well that supports getting and updating ref criteria.

 /tfs/*collectionName*/_apis/git/repositories/*repositoryId*/limitedRefCriteria

Interestingly, once I knew the "optimized" keyword, it looks like using _optimized in the repo name where the article describes using _full will also work to reverse the feature. Ex:

https://.visualstudio.com/Project/_git/_optimized/Repo

If you don't have the feature on by default but use the _optimized path, it will return the filtered branches. This might also be a safer path for those that don't want to mess with tweaking the settings json and only want to add records via stored proc to the limited refs criteria.

I think it's worth noting in a separate answer that this stuff works in Azure DevOps (hosted service).

If your clone URL is https://dev.azure.com/*orgname*/*projectname*/_git/*reponame*, then by inserting _optimized/ before the repo name (as in https://dev.azure.com/*orgname*/*projectname*/_git/_optimized/*reponame*), you get the "filtered refs" behavior that the article talks about.

(for SSH URLs it's the same idea, add _optimized/ right before the repo name near the end of the URL)

Furthermore, you can run GET and PUT on the limitedRefCriteria endpoint, for example with fetch requests in your browser session, to provide global visibility to additional branches besides the default, the user's own branches and the user's 'favorite' branches and namespaces:

List the repo's limitedRefCriteria:

fetch("https://dev.azure.com/*orgname*/_apis/git/repositories/*repoid*/limitedRefCriteria", {"credentials":"include","headers":{"accept":"application/json","x-requested-with":"XMLHttpRequest"},"method":"GET"}).then(r => {return r.json()}).then(d => console.log(d));

Set the repo's limitedRefCriteria:

fetch("https://dev.azure.com/*orgname*/_apis/git/repositories/*repoid*/limitedRefCriteria", {"credentials":"include","headers":{"accept":"application/json;api-version=6.0-preview.1;","x-requested-with":"XMLHttpRequest",'Content-Type': 'application/json'},"method":"PUT",body:JSON.stringify({refExactMatches:['refs/heads/some-specific-branch'], refNamespaces:['refs/heads/some-branch-prefix/']})}).then(r => {return r.json()}).then(d => console.log(d));

(unfortunately I found this by trial and error on the basis of the answer above, rather than any documentation available online, so I have to assume this is not officially supported...?)

Related