如何读取索引diff --git输出

时间:2013-11-26 09:12:26

标签: git diff patch

我有一个补丁看起来像

diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/x    c/xc.c
 15 index e220f68..e611b24 100644
 16 --- a/tools/python/xen/lowlevel/xc/xc.c
 17 +++ b/tools/python/xen/lowlevel/xc/xc.c
 18 @@ -228,6 +228,7 @@ static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
 19      int vcpu = 0, i;
 20      xc_cpumap_t cpumap;
 21      PyObject *cpulist = NULL;

我想知道哪个commit生成了补丁,以及如何解析补丁中的15 index e220f68..e611b24 100644

1 个答案:

答案 0 :(得分:1)

让我们来看看git show的输出。 (这是来自真实仓库的实际输出,尽管我会抓住大部分位。)

$ git show d362e62
commit d362e62490dd7f59c170a0a050a203fa0eda9f5a
[snip]
diff --git a/fmt.py b/fmt.py
index c44c267..ba772ee 100755
[snip]

在这里,d362e62是"短版本"提交的真实名称,即SHA-1。 "长" form是完整的40个字符的版本,这是git show输出的第一行。

除了提交文本之外,提交本身还包含一个"树" (零和更多"父母")。我们可以使用git cat-file -p

看到这一点
$ git cat-file -p d362e62
tree 0b9bebfee8890b242875af0df209fd9f335bf14d
parent 41f3a6bcba1f5f7059133f862727809f49ff4657
[snip author, committer, and commit text]

我们可以看一下"树"同样。我可以用"真名"上面的SHA-1,但是我在这里使用了一些git语法:提交标识符后跟^{tree}告诉git从提交ID中提取树ID。

$ git cat-file -p d362e62^{tree}
[snip]
120000 blob 7417b50d02819bbebeac0f4104850549935f7089    fmt
100755 blob ba772eeb6139de5a724d67d18ce01bfccaf57590    fmt.py
[snip]

我离开了fmt的行,因为它是fmt.py的符号链接。符号链接具有模式120000,它告诉git blob数据实际上是符号链接的目标。文件fmt.py具有模式100755,它告诉git它是一个普通文件并且它是可执行文件(它是一个Python脚本)。 这是您在100644行中看到的100755index的来源。

"真实姓名" git repo中的blob(文件对象)是40个字符的SHA-1。 fmt.py的7个字符的缩写版本为ba772ee这是..行中两个index分隔数字中的第二个号码。

该行的第一个号码是"真名称"在该文件的上一个版本的git repo中,即之前的fmt.py版本我创建了提交d362e62

我们可以使用另一些特殊的git语法来查看这些内容。 1 gitrevisions中所述,遵循带帽子字符的提交说明符(circumflex,向上箭头) ,无论你喜欢什么称呼它)^告诉git找到该提交的第一个父级。所以:

$ git rev-parse d362e62^
41f3a6bcba1f5f7059133f862727809f49ff4657

告诉我们在提交给git show的提交之前提交是名为41f3a6b...的提交。而且,当然,如果我们git cat-file -p,我们会使用另一个树进行另一次提交,如果我们git cat-file该树ID并查找fmt.py,我们会找到另一个blob与另一个SHA-1:

$ git cat-file -p 41f3a6b
tree cbfb63beec96eebf0c73ba6a501cc8151adfec8a
parent 80eeb496ea3f538aa14acdc6b0815024a5e99c7e
[snip]
$ git cat-file -p cbfb63beec96eebf0c73ba6a501cc8151adfec8a | grep fmt.py
100755 blob c44c267c4603838ac7a54aa450b33d0dd7a8bebc    fmt.py
$ 

并且它是:cc4c267是"真实姓名"的缩写形式。存储在上一个提交中的文件。 这是index行中的第一个号码。

我以长篇形式写下这一切,以说明git是如何从"点A"到" B"。但是,就像使用简写语法d362e62^{tree}一样,有一种非常简单的方法可以使用git rev-parse获取blob SHA-1值:

$ git rev-parse d362e62:fmt.py
ba772eeb6139de5a724d67d18ce01bfccaf57590
$ git rev-parse d362e62^:fmt.py
c44c267c4603838ac7a54aa450b33d0dd7a8bebc

如果您需要缩短版本,请使用git rev-parse --short将SHA-1值截断为(通常)7个字符。

所以:

  

我想知道哪个commit生成了补丁,以及如何解析补丁中的15 index e220f68..e611b24 100644

15(或某个地方的某个人)添加的行号,现在您知道index行上其余值是什么了。但要找到提交 -well,这是困难的部分。 commit 是查找其他值的内容。没有来自"其他值的链接"回到"提交":"箭头",因为它只是从提交到树,然后从树到blob。没有从blob到树的指针,也没有从树到提交的指针。

Git始终以某种外部指定名称开头。通常这是一个分支名称或标签,或一个"符号引用" (正如HEAD通常是,当你没有一个"分离的头")。引用定位提交。 2 如果引用是分支名称,则提交是"提示"那个分支。 3 如果它是一个标签,它仍然会找到一个提交。如果它是HEAD,而HEADmaster之类的分支的名称,则git会将HEAD变为master,然后转为{{ 1}}进入提交。换句话说,提交就是你开始的地方,通常是从name到commit-ID,但你几乎总能指定一个" raw"这里有SHA-1 ID。

一旦git具有commit-ID,该提交就会识别更多提交(其父项)和一棵树。树根据需要识别子树,树及其子树识别斑点。从具有"外部名称"的所有提交开始,git最终找到所有树和所有blob-并且存储库中以找到的任何树或blob都符合以下条件:垃圾收集,当您运行master时(或git gc自动运行时)。 (这是删除分支以及git内部创建的任何数量的特殊临时文件的方式,以后会被清除。)


1 Git有一个特殊语法的 lot 。在我看来,记住最有用的是:

  • 在事物之后的帽子=父母:git gc =" master^的父母"
  • 代码 master 在事件=备份 N 父母后:N ="祖父母{ {1}}"
  • master~2 =" master 选择的所有修订版,不包括 X..Y &#34选择的所有版本;:Y ="记录分支X上不在git log master..devel"
  • 上的所有提交

devel语法也在master中使用,但此处代替 .. 上的&#34;内容不在<{1}}上em> git diff &#34;,您可以直接将与 Y 相关联的版本与 {{1}相关联的版本进行比较}

2 我故意跳过注释标签&#34;,它们也有存储库实体。在某些情况下,git将访问标记对象,而在其他情况下 - 当需要提交时,树和/或blob-git将自动跟随带注释的标记。在内部,带注释的标签看起来与提交非常相似,除了它不是树和父类,它有一个对另一个git存储库对象的引用 - 通常直接提交到提交,但有时引用到另一个标记,理论上你可以创建一个树或blob的带注释标记,完全跳过提交部分。

3 分支名称始终指向其自己分支的提示,但该分支可能只是另一个分支的一部分。例如,假设您有一个很好的线性提交序列:

X

其中C7的C6为其母体,C6为C5,依此类推。如果分支标签X是对提交Y的引用,则分支X在C5结束。如果分支标签...<-- C3 <-- C4 <-- C5 <-- C6 <-- C7 指向C7,则分支Y在C7结束。在这种情况下,分支Y&#34;包含&#34;分支X,但反之亦然。