jgit git pull_使用JGit API探索Git内部

jgit git pull

您是否想过提交及​​其内容如何存储在Git中? 好吧,我有,在上一个下雨的周末我有一些空闲时间,所以我做了一些研究。

因为我对Java的感觉比对Bash的感觉要多,所以我使用JGit和一些学习测试来探究提交的Git内部。 这是我的发现:

Git –对象数据库

Git的核心是一个简单的内容可寻址数据存储。 这意味着您可以在其中插入任何类型的内容,并且它将返回一个密钥,您可以使用该密钥在以后的某个时间点再次检索数据。

对于Git,关键是根据内容计算出的20字节SHA-1哈希。 内容也被称为在GIT中术语的对象 ,因此数据存储也被称为对象数据库

让我们看看如何使用JGit来存储和检索内容。

斑点

在JGit中,ObjectInserter用于将内容存储到对象数据库中。 可以将其视为与Git中的git hash-object大致等效。

使用其insert()方法,您可以将对象写入数据存储,而其idFor()方法仅计算给定字节的SHA-1哈希。 因此,用于存储字符串的代码如下所示:

ObjectInserter objectInserter = repository.newObjectInserter();
byte[] bytes = "Hello World!".getBytes( "utf-8" );
ObjectId blobId = objectInserter.insert( Constants.OBJ_BLOB, bytes );
objectInserter.flush();

所有代码示例均假定存储库变量指向在代码段外部创建的空存储库 。

第一参数表示要插入的对象的对象类型 ,在这种情况下,斑点的类型。 还有其他对象类型,我们将在后面学习。 Blob类型用于存储任意内容。

有效负载必须在第二个参数中给出,在这种情况下,必须作为字节数组。 也可以使用接受InputStream的重载方法。

最后,需要刷新ObjectInserter以使更改对其他访问存储库的用户可见。

insert()方法返回根据类型,内容长度和内容字节计算得出的SHA-1哈希。 但是,在JGit中,SHA-1哈希是通过ObjectId类表示的,ObjectId类是一种不变的数据结构,可以在字节,整数和字符串之间来回转换。

现在,您可以使用返回的blobId取回内容,从而确保上面的代码实际写入了内容。

ObjectReader objectReader = repository.newObjectReader();
ObjectLoader objectLoader = objectReader.open( blobId );
int type = objectLoader.getType(); // Constants.OBJ_BLOB
byte[] bytes = objectLoader.getBytes();
String helloWorld = new String( bytes, "utf-8" ) // Hello World!

ObjectReader的open()方法返回一个ObjectLoader,该对象可用于访问由给定对象ID标识的对象。 借助ObjectLoader,您可以将对象的类型,大小以及内容作为字节数组或流获取。

要验证JGit编写的对象与本机Git兼容,可以使用git cat-file检索其内容。

$ git cat-file -p c57eff55ebc0c54973903af5f72bac72762cf4f4
Hello World!
git cat-file -t c57eff55ebc0c54973903af5f72bac72762cf4f4
blob

如果您在存储库的.git/objects目录中查找,则会找到一个名为'c5'的目录,其中包含名为'7eff55ebc0c54973903af5f72bac72762cf4f4'的文件。 内容的最初存储方式是这样的:每个对象作为单个文件,以内容的SHA-1哈希命名。 子目录以SHA-1的前两个字符命名,文件名由其余字符组成。

现在您可以存储文件的内容,下一步就是存储文件的名称。 而且可能不仅仅是一个文件,因为提交通常由一组文件组成。 为了保存此类信息,Git使用了所谓的树对象。

树对象

树对象可以看作是简化的文件系统结构,其中包含有关文件和目录的信息。

它包含任意数量的树条目。 每个条目都有一个路径名,文件模式,并指向文件(blob对象)或另一个(子)树对象的内容(如果它表示目录)。 指针当然是Blob对象或树对象的SHA-1哈希。

首先,您可以创建一个树,其中包含一个名为“ hello-world.txt”的文件的单个条目,该文件指向上面存储的“ Hello World!”。 内容。

TreeFormatter treeFormatter = new TreeFormatter();
treeFormatter.append( "hello-world.txt", FileMode.REGULAR_FILE, blobId );
ObjectId treeId = objectInserter.insert( treeFormatter );
objectInserter.flush();

TreeFormatter在这里用于构造内存中的树对象。 通过调用append(),将添加具有给定路径名,模式和ID的条目,条目的内容将存储在该ID下。

从根本上讲,您可以自由选择任何路径名。 但是,Git希望路径名是相对于工作目录的,且不带前导“ /”。

此处使用的文件模式表示正常文件。 其他模式是EXECUTABLE_FILE(它是一个可执行文件)和SYMLINK(它指定一个符号链接)。 对于目录条目,文件模式始终为TREE。

同样,您将需要一个ObjectInserter。 其重载的insert()方法之一接受TreeFormatter并将其写入对象数据库。

现在,您可以使用TreeWalk检索和检查树对象:

TreeWalk treeWalk = new TreeWalk( repository );
treeWalk.addTree( treeId );
treeWalk.next();
String filename = treeWalk.getPathString(); // hello-world.txt

实际上,TreeWalk旨在对添加的树及其子树进行迭代。 但是因为我们知道只有一个条目,所以对next()的单个调用就足够了。

如果使用本地Git查看刚刚编写的树对象,则会看到以下内容:

$ git cat-file -p 44d52a975c793e5a4115e315b8d89369e2919e51
100644 blob c57eff55ebc0c54973903af5f72bac72762cf4f4    hello-world.txt

现在您已经拥有提交的必要条件,让我们创建提交对象本身。

提交对象

提交对象 (通过树对象)引用构成提交的文件以及一些元数据。 详细而言,提交包括:

  • 指向树对象的指针
  • 指向零个或多个父提交的指针(稍后会详细介绍)
  • 提交消息
  • 以及作者和提交者

由于提交对象只是对象数据库中的另一个对象,因此它也被在其内容上计算的SHA-1哈希密封。

为了形成提交对象,JGit提供了CommitBuilder实用程序类。

CommitBuilder commitBuilder = new CommitBuilder();
commitBuilder.setTreeId( treeId );
commitBuilder.setMessage( "My first commit!" );
PersonIdent person = new PersonIdent( "me", "me@example.com" );
commitBuilder.setAuthor( person );
commitBuilder.setCommitter( person );
ObjectInserter objectInserter = repository.newObjectInserter();
ObjectId commitId = objectInserter.insert( commitBuilder );
objectInserter.flush();

使用它很简单,它具有提交所有属性的setter方法。

作者和提交者通过PersonIdent类表示,该类包含名称,电子邮件,时间戳和时区。 此处使用的构造函数应用给定的名称和电子邮件,并采用当前时间和时区。

其余的应该已经很熟悉了:ObjectInserter用于实际写入提交对象并返回提交ID。

要从存储库中检索提交对象,可以再次使用ObjectReader:

ObjectReader objectReader = repository.newObjectReader();
ObjectLoader objectLoader = objectReader.open( commitId );
RevCommit commit = RevCommit.parse( objectLoader.getBytes() );

生成的RevCommit表示具有与CommitBuilder中指定的相同属性的提交。

再一次-仔细检查git cat-file的输出:

$ git cat-file -p 783341299c95ddda51e6b2393c16deaf0c92d5a0
tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
author me <me@example.com> 1412872859 +0200
committer me <me@example.com> 1412872859 +0200My first commit!

父母

父母链构成了Git仓库的历史,并建模了有向无环图 。 这意味着提交“遵循”一个方向

一个提交可以有零个或多个父母。 存储库中的第一次提交没有父提交(aka根提交)。 第二个提交又将第一个提交作为其父级,依此类推。

创建多个根提交完全合法。 如果使用git checkout --orphan new_branch将创建一个新的孤立分支并将其切换到。 在此分支上进行的第一次提交将没有父项,并且将成为与所有其他提交断开连接的新历史记录的根。

jgit-commit-merge
如果开始分支并最终合并变化的分歧线,通常会导致合并提交 。 这样的提交具有分支的父分支作为其父分支。

为了构造父提交,需要在CommitBuilder中指定父提交的ID。

commitBuilder.setParents( parentId );

还可以查询RevCommit类,该类表示存储库中的提交,并且可以查询其父级。 其getParents()和getParent(int)方法返回全部或第n个父RevCommit。

请注意,尽管这些方法返回RevCommits,但这些方法尚未完全解决。 设置其ID属性后,所有其他属性(fullMessage,author,committer等)均未设置。 因此,例如,尝试调用parent.getFullMessage()将会引发NullPointerException。 为了实际使用父提交,您需要通过上面概述的ObjectReader检索完整的RevCommit,或者使用RevWalk加载和解析提交标头:

RevWalk revWalk = new RevWalk( repository );
revWalk.parseHeaders( parentCommit );

总而言之,请记住将返回的父提交视为ObjectId而不是RevCommits。

有关树对象的更多信息

如果要将文件存储在子目录中,则需要自己构造子树。 假设您要将文件“ file.txt”的内容存储在文件夹“文件夹”中。

首先,为子树创建并存储TreeFormatter,该子树具有文件的条目:

TreeFormatter subtreeFormatter = new TreeFormatter();
subtreeFormatter.append( "file.txt", FileMode.REGULAR_FILE, blobId );
ObjectId subtreeId = objectInserter.insert( subtreeFormatter );

然后,创建并存储一个TreeFormatter,其中包含一个表示文件夹并指向刚创建的子树的条目。

TreeFormatter treeFormatter = new TreeFormatter();
treeFormatter.append( "folder", FileMode.TREE, subtreeId );
ObjectId treeId = objectInserter.insert( treeFormatter );

jgit-internals树
条目的文件模式为TREE,表示目录,其ID指向保存文件条目的子树。 返回的treeId是将传递给CommitBuilder的那个。

Git对树对象中的条目要求一定的排序顺序。 我在这里找到的“ Git数据格式”文档指出:

树条目按包含条目名称的字节序列排序。 但是,出于排序比较的目的,比较树对象的条目,就好像条目名称字节序列具有尾随的ASCII'/'(0x2f)一样。

要读取树对象的内容,可以再次使用TreeWalk。 但是这一次,如果要访问所有条目,则需要告诉它递归到子树中。 而且,如果您希望看到指向树的条目,请不要忘记将postOrderTraversal设置为true。 否则将跳过它们。

最终,整个TreeWalk循环将如下所示:

TreeWalk treeWalk = new TreeWalk( repository );
treeWalk.addTree( treeId );
treeWalk.setRecursive( true );
treeWalk.setPostOrderTraversal( true );
while( treeWalk.next() ) {int fileMode = Integer.parseInt( treeWalk.getFileMode( 0 ).toString() );String objectId = treeWalk.getObjectId( 0 ).name();String path = treeWalk.getPathString();System.out.println( String.format( "%06d %s %s", fileMode, objectId, path ) );
}

…并将导致以下输出:

100644 6b584e8ece562ebffc15d38808cd6b98fc3d97ea folder/file.txt 
040000 541550ddcf8a29bcd80b0800a142a7d47890cfd6 folder

尽管我发现API不是很直观,但是它可以完成工作并显示树对象的所有详细信息。

总结Git内部

毫无疑问,对于常见用例,建议使用高级Add-和CommitCommands将文件提交到存储库。 不过,我发现值得深入研究JGit和Git,并希望您也这样做。 而且,在您需要将文件提交到没有工作目录和/或索引的存储库的情况下(这种情况不太常见),这里提供的信息可能会有所帮助。

如果您想亲自尝试此处列出的示例,建议您设置JGit并对其源代码和JavaDoc进行访问,以便获得有意义的上下文信息,内容帮助,调试源等。

  • 完整的源代码托管在这里: https : //gist.github.com/rherrmann/02d8d4fe81bb60d9049e

为简便起见,此处显示的示例省略了代码以释放分配的资源。 请参考完整的源代码以获取所有详细信息。

翻译自: https://www.javacodegeeks.com/2014/10/explore-git-internals-with-the-jgit-api.html

jgit git pull

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339429.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MFC实现Windows锁屏

编辑Windows锁屏锁屏软件相信大家都见过&#xff0c;以前我去网吧上网的时候也用过这个功能&#xff0c;当你有事情需要立即离开&#xff0c;而又不想让别人碰你的电脑&#xff0c;就需要用扫锁屏软件啦&#xff0c;锁住屏幕之后等回来的时候再输入密码解锁。同样的&#xff0c…

pdf 截图 java_java实现pdf文件截图的方法【附PDFRenderer.jar下载】

本文实例讲述了java实现pdf文件截图的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;最近做的一个网站中&#xff0c;有个需求是上传pdf文件&#xff0c;显示pdf的封页&#xff0c;点击封页之后进行在线阅读&#xff0c;这里使用的是PDFRender对pdf进行截图。pub…

检查Java测试中发生了什么

有人想到了在Java单元测试中使用try和catch块的想法&#xff1a; Test public void test() { try { callSomeCode(); } catch (Exception e) { assertEquals( "foo" , e.getMessage()); } } 上面的内容很诱人&#xff0c;但不起作用 。 如果被测代码没有抛出&…

学习红客技术必备

互联网时代已悄悄来临&#xff0c;作为新时代的人们&#xff0c;我们日常生活、工作、学习方面都需要借助互联网来完成&#xff0c;这样&#xff0c;又产生一种新的问题&#xff0c;那就是网络安全的问题&#xff0c;有时我们拼命加班好不容易完成的东西&#xff0c;在一夜之间…

md5withrsa java_浏览器运行java插件报错:Algorithm constraints check failed: MD5withRSA

今天使用kvm管理机房机器的时候发现一只连不上&#xff0c;报以下错误&#xff1a;sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Algorithm constraints check failed: MD5withRSA我确认我已经把…

jpa 实体映射视图_JPA教程:实体映射-第3部分

jpa 实体映射视图在上一篇文章中&#xff0c;我展示了两种读取/写入持久实体状态的不同方法-字段和属性。 使用字段访问模式时&#xff0c;JPA使用反射直接从实体的字段读取状态值。 如果我们没有明确指定列名&#xff0c;它将直接将字段名转换为数据库列名。 在属性访问模式下…

今晚课题:2019-3-20

今晚课题C/C万年历技术实现原理上课时间&#xff1a;20:30--22:30上课老师&#xff1a;杰越教育-Larry老师上课地址&#xff1a;https://ke.qq.com/course/353889 课程内容&#xff1a;1、C/Cfor逻辑原理2、重要点数据结构分析3、万年历效果实现展示赢在别人休息时&#xff0c;…

python在材料模拟中的应用_材料模拟python_模拟-python模拟-在不妨碍实现的情况下修补方法...

此答案解决了Quuxplusone用户提供的赏金中提到的其他要求&#xff1a;对于我的用例而言&#xff0c;重要的是它可以与MagicMock一起使用&#xff0c;即&#xff0c;它不需要我在构造Potato(在此示例中为spud)实例与调用spud.foo(在本例中)之间插入任何代码。我需要293984865472…

新版本的Selenium 4 Alpha会有什么期望?

我们所有人都属于测试领域&#xff0c;他们熟悉Selenium&#xff0c;Selenium是业界最流行的开源自动化工具之一。 Selenium的创始成员Simon Stewart在2018年8月正式宣布Selenium 4的发布日期以及它将为用户带来哪些新功能时&#xff0c;我们感到非常兴奋。 与Selenium 3一样&…

今晚课题:2019-3-22

今晚课题数据结构必会重点集合上课时间&#xff1a;20:30--22:30上课老师&#xff1a;杰越教育-Larry老师上课地址&#xff1a;https://ke.qq.com/course/353889 课程内容&#xff1a;1、C/C技术工作运用2、数据结构重点数组定义特点3、工作项目数组合理使用赢在别人休息时&…

java 单例 实现_java 实现单例的各种方式

概述上一篇日志中&#xff0c;我们介绍了单例模式的概念和基础的应用本节中&#xff0c;我们就来介绍一下 java 语言中如何编写单例模式类只适合单线程环境的单例模式public class Singleton {private static Singleton instance null;private Singleton() { }public static S…

Drools DMN最新开源引擎性能改进

我们一直在寻求改善Drools DMN开源引擎的性能。 我们最近审查了DMN用例&#xff0c;其中输入数据节点的实际输入总体有所不同。 这突出显示了引擎的次佳性能&#xff0c;我们在最新版本中对此进行了改进。 我想分享我们的发现&#xff01; 基准制定 当我们开始为该用例运行一个…

今晚课题:2019-3-23

今晚课题剖析《服务器高并发-IOCP模型架构》上课时间&#xff1a;2019/03/23 20:30--22:30授课讲师&#xff1a;杰越教育C/C学院--Vico课程链接&#xff1a;https://ke.qq.com/course/353889?tuin7472c9c 课程内容&#xff1a; 1、C/C编程语言入门精通 2、C线程技术在服务器…

使用Selenium WebDriver测试自动化的22条实用技巧

使用Selenium进行测试自动化已使全球的网站测试人员能够轻松执行自动化的网站测试。 Webdriver是Selenium框架的核心组件&#xff0c;通过它您可以针对不同类型的浏览器&#xff08;例如Google Chrome&#xff0c;Mozilla Firefox&#xff0c;Safari&#xff0c;Opera&#xff…

java编译源文件_Java源文件编译示例

java程序编译java源文件JavacCompile文件&#xff1a;package yan.demo.javac;import java.io.File;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import javax.tools.Diagnostic;import javax.tools.DiagnosticCollector;import javax.tools.Fi…

这么奇葩搞笑的代码注释你见过吗

程序员作为一种“异类”&#xff0c;虽然他们平时给人们的留下的印象并不太好&#xff0c;觉得他们只会写代码。但是有的时候不得不佩服他们天马行空的想象力&#xff0c;他们可能会利用注释让你噗嗤一笑&#xff0c;下面我们来看看那些奇葩搞笑的代码注释吧。注释1&#xff1a…

facelets_不要在facelets中重复表情

facelets您是否曾经在JSF中看到过像这样的重复EL表达式&#xff1f; <h:inputText value"#{oneBean.name}" rendered"#{anotherBean.showPerson}"/> <h:inputText value"#{oneBean.birthday}" rendered"#{anotherBean.showPerson…

C语言与Java的深情对话:儿子,还得多练几年啊!老子还是老子

很多小伙伴都老是会碰到疑问&#xff0c;其实还是基础没打扎实&#xff0c;这些题如果你不看答案你能知道多少呢&#xff1f;如果还有很多不知道就证明基础没打扎实&#xff0c;如果你还在入门纠结&#xff0c;如果你还在苦恼怎么入门&#xff01;小编有个建议&#xff0c;可以…

Servlet和JSP之间的区别

JSP和Servlet都是与使用Java构建基于Web的应用程序有关的重要概念。 基本上&#xff0c;Servlet是Java中HTML&#xff0c;而JSP是HTML中的Java。 任何典型的Web开发面试都可能有几个基于JSP和Servlet的Java面试问题 。 尽管JSP和Servlet的主要目的是相同的&#xff0c;但是两者…

BAT人脸识别功能第二步-人脸检测

今晚课题点击【阅读原文】或长按图片【识别图中的二维码】即可参加今晚的课程。