我是新使用mercurial的团队的一员,我们已经确定,当合并发生时,手动合并的文件中会有更多错误。是否有可能从mercurial日志(即在某人完成合并并将合并变更集推送到中央存储库之后)来检测哪些文件是手动合并的?
答案 0 :(得分:3)
注意,我不知道这是否万无一失。此外,它需要我的尚未完成的Mercurial库for .NET的副本,可能只在Windows上运行,并且有点粗糙。
注意:我假设“手动合并”,你的意思是“文件Mercurial没有为我们自动合并”
这样的文件仍然可以通过外部工具进行一些或完全自动合并,但如果上述假设足够好,请继续阅读。
但是,我所做的是有效地运行测试存储库中的所有合并,重新进行合并并要求Mercurial仅使用其内部合并工具,如果文件无法由Mercurial自动合并,则会使文件无法解析,然后报告所有未解析的文件,清理合并,然后转到下一个合并变更集。
您需要的库(目前仅以源代码形式提供,我告诉您它尚未完成):
我在底部附加了一个zip文件,其中包含所有内容,测试存储库,脚本和库的二进制副本。
脚本(我使用LINQPad编写并测试它,测试库的输出如下):
void Main()
{
var repo = new Repository(@"c:\temp\repo");
var mergeChangesets = repo.Log(new LogCommand()
.WithAdditionalArgument("-r")
.WithAdditionalArgument("merge()")).Reverse().ToArray();
foreach (var merge in mergeChangesets)
{
Debug.WriteLine("analyzing merge #" + merge.RevisionNumber +
" between revisions #" + merge.LeftParentRevision +
" and #" + merge.RightParentRevision);
// update to left parent
repo.Update(merge.LeftParentHash);
try
{
// perform merge with right parent
var mergeCmd = new MergeCommand();
mergeCmd.WithRevision = merge.RightParentHash;
repo.Execute(mergeCmd);
// get list of unresolved files
var resolveCmd = new ResolveCommand();
repo.Execute(resolveCmd);
var unresolvedFiles = new List<string>();
using (var reader = new StringReader(resolveCmd.RawStandardOutput))
{
string line;
while ((line = reader.ReadLine()) != null)
if (line.StartsWith("U "))
unresolvedFiles.Add(line.Substring(2));
}
// report
if (unresolvedFiles.Count > 0)
{
Debug.WriteLine("merge changeset #" + merge.RevisionNumber +
" between revisions #" + merge.LeftParentRevision +
" and #" + merge.RightParentRevision + " had " +
unresolvedFiles.Count + " unresolved file(s)");
foreach (string filename in unresolvedFiles)
{
Debug.WriteLine(" " + filename);
}
}
}
finally
{
// get repository back to proper state
repo.Update(merge.LeftParentHash, new UpdateCommand().WithClean());
}
}
}
public class MergeCommand : MercurialCommandBase<MergeCommand>
{
public MergeCommand()
: base("merge")
{
}
[NullableArgumentAttribute(NonNullOption = "--rev")]
public RevSpec WithRevision
{
get;
set;
}
public override IEnumerable<string> Arguments
{
get
{
foreach (var arg in base.Arguments)
yield return arg;
yield return "--config";
yield return "ui.merge=internal:merge";
}
}
protected override void ThrowOnUnsuccessfulExecution(int exitCode,
string standardOutput, string standardErrorOutput)
{
if (exitCode != 0 && exitCode != 1)
base.ThrowOnUnsuccessfulExecution(exitCode, standardOutput,
standardErrorOutput);
}
}
public class ResolveCommand : MercurialCommandBase<MergeCommand>
{
public ResolveCommand()
: base("resolve")
{
}
public override IEnumerable<string> Arguments
{
get
{
foreach (var arg in base.Arguments)
yield return arg;
yield return "--list";
}
}
}
示例输出:
analyzing merge #7 between revisions #5 and #6
analyzing merge #10 between revisions #9 and #8
merge changeset #10 between revisions #9 and #8 had 1 unresolved file(s)
test1.txt
包含所有内容的Zip文件(LINQPad脚本,Mercurial.Net程序集,如果您不信任我就编译它,以及我在上面执行它的测试存储库):
BIG CAVEAT :仅在您的存储库的克隆中运行它!如果这会破坏您的存储库,我将不会承担任何责任,但我认为这不太可能。
答案 1 :(得分:2)
Tis是Lasses回答的shell脚本变体:
#!/bin/bash
test "$1" = "--destroy-my-working-copy" || exit
hg log -r 'merge()' --template '{parents} {rev}\n' | sed -e 's/[0-9]*://g' | while read p1 p2 commit
do
echo "-------------------------"
echo examine $commit
LC_ALL=C hg up -C -r $p1 >/dev/null
LC_ALL=C hg merge -r 26 --config ui.merge=internal:merge 2>&1 | grep failed
done
hg up -C -r tip > /dev/null
示例输出:
> mergetest.sh --destroy-my-working-copy
-------------------------
examine 7
-------------------------
examine 11
-------------------------
examine 23
-------------------------
examine 31
-------------------------
examine 37
merging test.py failed!