LibGit2Sharp 库开源地址: https://github.com/libgit2/libgit2sharp
本文使用的版本是: 0.31.0
按照 dotnet 的惯例,使用之前先用 NuGet 安装,安装之后的 csproj 文件代码大概如下
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net9.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup><ItemGroup><PackageReference Include="LibGit2Sharp" Version="0.31.0" /></ItemGroup></Project>
我将使用我的博客代码仓库作为测试仓库,其本地路径地址是 C:\lindexi\Code\lindexi\.git\
还请大家更换为自己的文件夹
仓库初始化
var folder = @"C:\lindexi\Code\lindexi\.git\";var repository = new Repository(folder);
仓库初始化过程中需要传入的是 .git
文件夹路径
判断给定路径是否被忽略
比如判断 bin\obj\Foo.exe
文件是否应该在此 git 忽略列表内,可使用如下代码
bool isPathIgnored = repository.Ignore.IsPathIgnored("bin/obj/Foo.exe");
以上代码的细节是路径斜杠需要使用 /
斜杠
获取 commit 的变更差异 Patch 内容
获取某个 commit 更改的文件,以及这些文件的更改内容,生成 Patch 文本的方法如下
var queryableCommitLog = repository.Commits;
Commit commit = queryableCommitLog.First();var patch = repository.Diff.Compare<Patch>(commit.Parents.First().Tree, commit.Tree);foreach (PatchEntryChanges patchEntryChanges in patch)
{var path = patchEntryChanges.Path;string patchText = patchEntryChanges.Patch;
}
以上逻辑就是执行当前的 commit 和上一个 commit 的对比差异,通过差异的 Patch 获取当前的变更差异内容
以上的 patchText
可能的输出内容大概如下
diff --git a/Workbench/ChearjinohecelKafemlairreena/Program.cs b/Workbench/ChearjinohecelKafemlairreena/Program.csindex 63d0e46..6a80004 100644--- a/Workbench/ChearjinohecelKafemlairreena/Program.cs+++ b/Workbench/ChearjinohecelKafemlairreena/Program.cs@@ -14,11 +14,18 @@ bool isPathIgnored = repository.Ignore.IsPathIgnored("bin/obj/Foo.exe");var queryableCommitLog = repository.Commits;Commit commit = queryableCommitLog.First();-var remoteCollection = repository.Network.Remotes;+ObjectId commitId = commit.Id;+GitObject gitObject = repository.Lookup(commitId);++TreeChanges treeChanges = repository.Diff.Compare<TreeChanges>(commit.Parents.First().Tree,commit.Tree);+foreach (TreeEntryChanges treeEntryChanges in treeChanges)+{+ var path = treeEntryChanges.Path;+ var changeKind = treeEntryChanges.Status;+}HistoryDivergence historyDivergence = repository.ObjectDatabase.CalculateHistoryDivergence(queryableCommitLog.Skip(100).First(), commit);var historyDivergenceCommonAncestor = historyDivergence.CommonAncestor;-GC.KeepAlive(repository);Console.WriteLine("Hello, World!");
以上为一个个文件的获取 Patch 内容。获取整个 commit 的 Patch 内容可直接使用 Content 属性,如以下代码所示
var patch = repository.Diff.Compare<Patch>(commit.Parents.First().Tree, commit.Tree);
var patchContent = patch.Content;
以上的 patchContent
就是整个 commit 的 Patch 内容,包含所有影响的文件和影响的内容
如果一个 commit 属于一个 Merge 的 commit 则可能 Parents 包含多项,这一点还需要大家根据自己的业务进行设置
查看历史差异
查看两个 commit 之间的历史差异,如哪个在前哪个在后,以及中间过程差了多少个 commit 数量,代码如下
var queryableCommitLog = repository.Commits;HistoryDivergence historyDivergence = repository.ObjectDatabase.CalculateHistoryDivergence(queryableCommitLog.Skip(100).First(), commit);
var historyDivergenceCommonAncestor = historyDivergence.CommonAncestor;
以上代码我特意选用了 Skip(100)
跳过当前 100 个 commit 去查找其差异作为示例
查看指定文件的 Git 历史
如以下代码,查看 Workbench/ChearjinohecelKafemlairreena/Program.cs 文件的变更历史
var queryableCommitLog = repository.Commits;var logEntries = queryableCommitLog.QueryBy("Workbench/ChearjinohecelKafemlairreena/Program.cs");
foreach (LogEntry logEntry in logEntries)
{
}
这里的细节是斜杠需要使用 /
斜杠
代码
以上代码放在 github 和 gitee 上,可以使用如下命令行拉取代码。我整个代码仓库比较庞大,使用以下命令行可以进行部分拉取,拉取速度比较快
先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 60c472a79bfbc32b5b18071d5dec2f05046ff4db
以上使用的是国内的 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码。如果依然拉取不到代码,可以发邮件向我要代码
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 60c472a79bfbc32b5b18071d5dec2f05046ff4db
获取代码之后,进入 Workbench/ChearjinohecelKafemlairreena 文件夹,即可获取到源代码
大家可以尝试拉取项目代码跑跑看。 此问题已经和 WPF 官方报告,详细请看 https://github.com/dotnet/wpf/issues/10093
更多技术博客,请参阅 博客导航