我正在使用 libgit2sharp 执行变基操作,它工作得很好,但是 我想在发生冲突时跳过变基步骤(如果提交有特定消息)
rebaseResult = _repository.Rebase.Start(branch, GetBranch(requiredBaseBranch), null, new Identity(_configuration.CommitUserName, _configuration.CommitEmailAddress), options);
if (rebaseResult.Status == RebaseStatus.Complete)
return true;
else
{
if (rebaseResult.Status == RebaseStatus.Conflicts)
{
var currentStep = _repository.Rebase.GetCurrentStepInfo();
if (currentStep.Commit.Message.Trim().EndsWith("Update packages", StringComparison.OrdinalIgnoreCase))
{
//is it possible to somehow skip and continue?
}
}
}
可能吗? 我看了一下,API似乎不直接支持它,但也许有一些更复杂的方法来实现这一点......
我最终编写了一个基于命令行的小型类,它跳过了变基。 发布对我有用的完整解决方案,以供将来参考:
public class PoorManRebaseMachine
{
private readonly Action<string, ConsoleColor> _logDelegate;
private readonly string _localRepoPath;
public PoorManRebaseMachine(string localRepoPath, Action<string, ConsoleColor> logDelegate)
{
_logDelegate = logDelegate;
_localRepoPath = localRepoPath;
}
public bool TryPoorManRebase(string storyNumber)
{
var errorOutput = RunGitCommandProcess("rebase master");
if (IsUpdatePackagesRebaseConflict(errorOutput, storyNumber))
{
try
{
return TrySkippingUpdatePackagesCommitsRecursive(storyNumber, errorOutput);
}
catch (Exception ex)
{
_logDelegate($"Exception while attempting automated rebase: {ex}", ConsoleColor.Red);
return false;
}
}
_logDelegate($"Will not attempt automated rebase due to a conflict not resolvable automatically: {errorOutput}", ConsoleColor.Red);
return false;
}
private bool TrySkippingUpdatePackagesCommitsRecursive(string storyNumber, string lastError)
{
if (IsUpdatePackagesRebaseConflict(lastError, storyNumber))
{
_logDelegate($"{GetRebaseStepNumber(lastError)} - Skipping rebase of: {GetRebaseConflictInfo(lastError)}", ConsoleColor.Cyan);
var errorOutput = RunGitCommandProcess("rebase master");
if (errorOutput.Contains("Successfully rebased and updated"))
{
_logDelegate($"Automated rebase done: {errorOutput}", ConsoleColor.Green);
return true;
}
_logDelegate($"{GetRebaseStepNumber(lastError)} - DONE, Starting {GetRebaseStepNumber(errorOutput)}", ConsoleColor.DarkCyan);
return TrySkippingUpdatePackagesCommitsRecursive(storyNumber, errorOutput);
}
throw new InvalidOperationException($"The rebase conflict {lastError} cannot be solved automatically");
}
private static bool IsUpdatePackagesRebaseConflict(string conflictMessage, string storyNumber) => System.Text.RegularExpressions.Regex.IsMatch(conflictMessage, $"Could not apply .+... {storyNumber}[ -]*Update packages");
private static string GetRebaseStepNumber(string conflictMessage) => conflictMessage.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
private static string GetRebaseConflictInfo(string conflictMessage)
{
var line = conflictMessage.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
return line?.Replace("Could not apply ", "");
}
private string RunGitCommandProcess(string commandName)
{
var p = new Process();
var si = new ProcessStartInfo("git", commandName)
{
WorkingDirectory = _localRepoPath,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
p.StartInfo = si;
p.Start();
_ = p.StandardOutput.ReadToEnd(); //need to read output, as without it sometimes the process hangs on reading error
var errorOutput = p.StandardError.ReadToEnd();
p.WaitForExit();
return errorOutput;
}
}