Ответ 1
TFS не обязательно создает кандидаты слияния на основе объектов ветвей для обратной совместимости (объекты ветвления были новыми в TFS 2010) и для поддержки необоснованных слияний (как только вы выполняете необоснованное слияние между двумя путями, они будут сохранены с объединением отношения для будущих слияний.)
Я бы предложил использовать специальную политику регистрации, которая предусматривает, что слияния идут из Dev → Test или Test → Dev и не пропускают промежуточный уровень. Это также позволяет сохранить Dev как объект ветвления, поэтому вы все равно получите все приятные функции, такие как визуализация ветвей.
Я могу привести очень грубый, очень псевдокодиальный пример того, что я имел в виду. (Это грубо и потому, что я ленив, и потому, что я трачу свое время в Java SDK, а не на .NET SDK, и понимаю, что большинство людей хотят проводить политику регистрации .NET. Но в основном потому, что я ленив.)
/*
* Create a dictionary of merge targets to allowable merge sources.
* For an item in this list, the allowable merge sources are a whitelist.
*/
private readonly Dictionary<String, List<String>> restrictedMergeTargets =
new Dictionary<String, List<String>>();
public static MergeWhitelistPolicy
{
/* Only allowed merges to $/Main from $/Test. */
List<String> mainWhitelist = new List<String>();
mainWhitelist.add("$/Test");
allowedMerges.put("$/Main", mainWhitelist);
/* Only allow merges to $/Test from $/Dev. */
List<String> testWhitelist = new List<String>();
testWhitelist.add("$/Dev");
allowedMerges.put("$/Test", testWhitelist);
}
public PolicyFailure[] evaluate(PolicyContext context)
{
PendingChange[] pendingChanges = GetPendingCheckin().GetCheckedPendingChanges();
foreach(PendingChange change : pendingChanges)
{
if(! change.IsMerge())
{
continue;
}
foreach(KeyValuePair<String, List<String>> restrictedTarget : restrictedMergeTargets)
{
if(VersionControlPath.IsChild(restrictedTarget.GetKey(), change.GetServerItem())
{
/* Whitelisted merge path - investigate. */
foreach(String allowedSource : restrictedTarget.GetValue())
{
foreach(MergeSource mergeSource : change.GetMergeSources())
{
if(! VersionControlPath.IsChild(allowedSource, mergeSource.GetServerItem()))
{
return new PolicyFailure("Merge from " +
mergeSource.GetServerItem() + " to " +
change.GetServerItem() + " is disallowed.");
}
}
}
}
}
}
return null;
}
Конечно, есть несколько проблем. Вы, конечно же, не хотели бы жестко кодировать список приемлемых отношений слияния в политике - вы могли бы экрнализировать его в файл конфигурации или вы могли бы запрашивать отношения слияния на сервере и кэшировать их, если бы у вас были определенные правила, такие как только прямые потомки слияния. (Кэширование это важно, поскольку проверка политики проверки выполняется часто и, как ожидается, будет быстрой. Иногда она может запускаться в потоке пользовательского интерфейса (хотя я сомневаюсь), поэтому ваш пробег может отличаться.)
Кроме того, мой код тестирования пути довольно неряшлив, в основном просто для сохранения некоторого пробела в моем комментарии. (И также, вышеупомянутая лень с моей стороны.)
Надеюсь, это хорошее начало.