我的git文件是最新版本吗?

时间:2017-02-12 02:17:32

标签: git

我想运行一个命令来查找“这是这些文件的最新版本吗?”

这里的目标是如此发现:“我在这里的文件是在回购中的前方还是后方?” ... ...如果存在差异,哪些不同(所以我以后可以运行git diff)

同样,如何找到提交顺序? (在颠覆中,它是一个整数,显然41落后于42.在git ......它们都是哈希。

2 个答案:

答案 0 :(得分:3)

这个问题没有很好地形成 - 因为至少在某种程度上,正如你所指出的,哈希不利于订购。

事实证明,首先没有订单。或者,更准确地说,有partial order但不一定是任何单个总订单。即使在Mercurial中也是如此,它(如Subversion)具有线性增加的修订计数(因此,如果存在至少43个修订版,则存在修订版41,后跟修订版42),因为这些Mercurial版本号是 local:它们特定于存储库的一个特定克隆。同一个存储库的另一个克隆可以在其中具有相同的提交,但是以另一个顺序。

(当版本首次存储在存储库中时,会分配Mercurial的顺序版本号,但是两个彼此不同步的克隆,然后重新同步,将包含相同的提交以不同的顺序。例如,在你自己的存储库X中,提交41显然在42之前出现。但这是因为你写了#41 ......当你的#41进入你的co-工作人员的存储库Y,你的#41成为他们的#42,因为他们在你写#41时写了你现在的#42。他们将他们的#41发送到他们的存储库Y它变成了他们的#41。那么你们每个人都给了另一个提交,并从另一个提交了一个提交,那就是你们俩有#41和#42,但顺序相反。)

此属性是任何分布式版本控制系统的基础:Subversion只能提供这种独特的线性化,因为它分布式;相反,中央服务器分配修订号。 (理论上,人们可以构建一个分布式系统,它使用来自中央服务器的预订,编号中可能存在漏洞,但编号也是顺序的。我从未见过有人这样做过它提出了有趣的同步问题。特别是,您不能分发保留号已被取代的提交;相反,您必须获得一个新的更高的数字。)

回到手头的问题,让我们定义足够多的项目,看看Git如何处理 - 或者有时候不会处理这个问题。

存储库中的内容

首先,Git有存储库,它存储了一组提交和其他三种对象类型。其他三个是带注释的标签 blobs (文件,本质上)。存储模型不需要带注释的标签,因此我们可以忽略它们,而树在对象哈希值和文件/路径名之间进行映射,blob只存储未解释的文件数据。

commit 是这里最有趣的对象类型。它存储:

  • 树ID,以便存储文件的快照;
  • 任意数量的父提交 ID,但通常只有1:这决定了提交的顺序;
  • 作者(用户名,电子邮件地址和时间戳);
  • 一个提交者(与作者相同,除了"谁编写了代码"它"谁将该代码放入存储库":这是为了处理电子邮件补丁,例如);和
  • 任意提交消息。

除了这些提交之外,存储库还存储了许多引用,其中最以用户为导向的是分支名称(如master)和< em>标签名称(如v1.2)。 引用仅仅是名称/对象ID对,并且分支引用被约束为仅包含提交对象的ID。如果名称master包含ID 1234567(缩写),我们会说master 指向提交1234567。标记名称通常指向标记对象,而不是直接指向提交;但如果是这样,标签对象则指向提交。 1

除了提交和其他对象之外,存储库还包含索引。索引有几个角色,但是对于我们来说,这里的重要角色是,你可以让Git构建你将要创建的 next 提交。索引开始填充当前提交的内容。然后,您git add个文件来更新它们,或者将新的文件添加到索引中。当你git commit结果时,Git获取当前的索引内容并从它们进行提交 - 尽管说它将索引转换为某些树对象更精确,然后进行提交{ {1}}是它刚刚制作的顶级树。

大多数存储库还包括工作树(拼写有或没有连字符,有时称为&#34;工作树&#34;)。工作树只是一个文件具有计算机其余部分可以处理的形式的地方:您可以编辑它们,编译它们(如果它们是源代码),等等,以及编辑器和程序之类的程序。编译器和Web服务器可以读取它们。实际存储在存储库中的文件采用仅Git格式,因此工作树提供了一个可以实际使用的区域,并对其进行处理。

1 事实上,标记对象可以指向任何其他对象,包括另一个标记,或树或blob。尽管如此,这种能力大多未被使用。

提交包含快照

请注意,在上面的描述中,我提到tree将当前索引转换为某些树,并从顶级树进行提交。这会以上次git commit编辑的形式保存文件。这意味着每个提交在提交时都有每个文件,完整且完整。这比最初的预期占用空间更少,因为大多数提交保留了大多数文件与之前的提交保持不变 - 因此它们最终会重新使用底层的Git blob对象。此外,每个Git对象都存储有zlib compression(除此之外,最终Git对象是&#34;打包&#34;,但这超出了本答案的范围)。因此,尽管每个提交都有一个完整的每个文件的副本,Git存储库往往不会膨胀很多。 2

2 如果您提交了大量压缩文件的轻微变体,例如bzipped或gzipped tar文件,则会出现此规则的明显异常。在这种情况下,你打败了Git的打包文件存储格式,尽管打包,但存储库迅速增长并变得不可行。如果你允许Git存储解压缩的,永不压缩的存档,Git的存储系统运行良好,存储库仍然可以管理。

提交形成图表;图表确定顺序

当提交git add包含另一个提交的ID为C的父级时,我们会说C 指向就像我们说C指向一些提交一样。因此,如果存储库中有三个提交,master是第一个,A是第二个,B是最后一个,我们可以绘制一个

C

此处A <- B <- C <-- master 指向master; C指回C;并B指向BA并未提前指出任何地方 - 它不能;这是第一次提交。它有 no 父项,称为 root commit

Git 使用名称A查找这些提交。分支名称 - 或者实际上,任何Git引用 - 都充当了启动Git的关键,提供了大丑陋的哈希ID。一旦Git找到提交master,它就会使用C查找CB来查找B

我们致电A的{​​{1}}和B 后代CA 祖先A。箭头连接&#34;孩子&#34;回到父母&#34;是单向链接,因此在提交时,找到提交的子项相对比较困难;但找到父母是微不足道的。

如果有分支,则会发生分支,因为两个后代最终共享父分支。例如,我将停止绘制内部箭头 - 请考虑此图:

B

这里有两个名字让Git开始。一个是Git从提交C开始,另一个是提交A--B--C <-- mainline \ D--E <-- feature 。按照内部向后箭头,我们从CEE,从DB。 (并且,我们像往常一样从C转到B,但现在它只是一条共同的线,它不再那么有趣了。)

我们说在分支主线&#34;上提交B是&#34;而在分支功能&#34;上提交A是&#34;。也就是说,提交A--B--CA--B--D--E位于两个分支上。 这个想法是Git所特有的。例如,Mercurial 这样做(无论如何都使用命名分支;你可以在一个分支中拥有匿名的Mercurial头,然后同样的问题突然出现,效果相同)。同样值得注意的是,我们可以稍微改变相同的图形以强调共享:

A

在任何情况下,关键概念是提交可以同时在许多分支上,并且确定提交的顺序通过这些父母/子女,祖先/后代的关系。

这对您的原始问题意味着什么

你想知道如何判断文件是否在&#34;之前&#34;或&#34;背后&#34;某些特定的提交,答案是,你不能。例如,假设您有文件B并且可以检查其内容;并假设您的存储库具有上图中的五个提交 C <-- mainline / A--B \ D--E <-- feature README.txt

进一步假设A与提交EREADME.txtREADME.txt中的B匹配,但不匹配D中的E,而不是A中的那个。 <{1}} 之前是什么?是落后的东西?好吧,匹配 CREADME.txtB;但这就是我们所能说的。

如果我们采用更大的文件集合 - 例如整个工作树 - 我们可以将它与任何提交进行比较。但是,我们要么得到&#34;它匹配&#34;或者&#34;它不匹配&#34;。如果它不匹配,D将为您提供一组指令:&#34;以下是如何更改提交以使其看起来像工作树&# 34; (反之亦然,你的选择)。但同样,您无法判断这是提前,还是背后,或者只是混淆了(如果您故意提取每个单独的文件)从一个随机选择的提交,例如 - 谁知道为什么,也许是午夜的疯狂:-))。

可以告诉您提交的内容

可以非常轻松地确定一次提交是否是另一次提交的祖先。例如,只给出两个提交哈希值,例如Egit diff,我们可以问:其中之一&#34;之前&#34;另一个?如果badf00d恰好是提交c0ffee1的ID而badf00d是提交B的ID,那么是,c0ffee1

但如果E是ID,而不是badf00d < c0ffee1,而不是badf00d,该怎么办?在{&#34;之前B来了吗? CC之前是E吗?答案可能是mu,例如在Hofstader和Persig意义上。

(要对此进行测试,请使用E

C

如果第一次提交是第二次提交的祖先,则返回true,即0,退出状态。请注意,如果答案是&#34; no&#34;,您仍然必须重复测试,以免任何一方成为另一方的祖先。)

答案 1 :(得分:0)

您可以将文件与diff进行比较(remote/<branch>),以查找是否有任何更改。

$ git fetch
$ git diff HEAD..origin/master       # diff with origin/master (remote master)