git:跨叉子的文件历史记录

时间:2018-05-08 22:13:36

标签: git

我的公司最近从Clearcase迁移到GIT。我们想知道是否有办法在forked repos中显示文件历史记录?我们的开发包括核心产品回购和一系列“项目叉”。维护人员和开发人员希望能够从特定仓库的所有分支(父代)中查看单个文件更改。这有点像CC中的“版本树”功能。我们有很多分叉,每个开发人员都要克隆它们然后搜索每个克隆是不切实际的。我们使用Bitbucket 5.3

1 个答案:

答案 0 :(得分:1)

Git没有拥有"文件历史记录"。 Git已提交,并且提交历史记录,因为每个提交都有一些父提交。当我们或Git链接提交到其父项,然后使用其父项链接到更多父项时,我们得到一个图:

A <-B <-C   <--master
     \
      D   <--develop

此处,名称master选择提交C,其父项为提交B。名称develop选择提交D,其父级也提交B。提交B已将提交A作为其父级,并且由于此存储库非常小,因此提交A是第一次提交,并且根本没有父级。

因此,此存储库中的历史记录是C导致B导致AD导致B导致C我们已经看到。那历史。那个所有有... 除了 ......

嗯,我们知道每次提交都是所有文件的快照。因此,提交B中包含一些文件。提交C还包含所有文件的快照。如果提交B中的文件集与提交README中的文件集匹配,除了一个特定的文件,例如README不同的文件,为什么然后呢? ,我们可以合成文件C的历史记录:{em}在B中相对于其父C 进行了更改。

该文件只是那里BB,但它们在这两次提交中不同。这两个提交已关联 - CC的父级(这意味着Bdevelop的孩子,但我们必须< em> compute ,因为Git只存储向后链接)。因此,这允许我们合成文件历史记录:我们查看提交历史记录,并提取有关我们关心的文件的信息。如果从一个孩子改回回到其父母,我们可以声称这是一个有趣的变化,记录孩子和父母ID(如果孩子只有一个父母,我们甚至不需要记录父母身份。)

添加新提交只会添加更多历史记录

假设我们有上面的四个提交存储库,我们克隆它以便我们可以处理它。在我们的克隆中,我们检查分支D,以便提交HEAD是当前提交,我们的develop附加到名称A--B--C <-- master \ D <-- develop (HEAD)

README

我们现在编辑文件git add README,运行git commit,然后运行E。我们的Git创建了一个新的提交E,它获取了一个新的,独特的,丑陋的哈希ID,并将其存储在我们的存储库中。它将D设置为git commit - 我们运行E时的当前提交 - 然后存储develop&#39}我们名称A--B--C <-- master \ D--E <-- develop (HEAD) 中的哈希ID,给我们:

develop

我们的名称E现在指向提交D而不是提交README

如果我们现在希望检查文件E的历史记录,我们必须从提交C 提交README开始,然后向后工作。 ED更改为E了吗?是的,所以提交D(父README)很有意思。 CB更改为C了吗?是的,所以提交B(父README)很有意思。我们必须对此存储库中的每个提交重复此操作,并为我们提供文件origin的合成历史记录。

关于&#34;分叉&#34;

fork只是某个其他存储库的克隆,但是使用某种 intent 创建的,通常用于将更改提供回原始存储库和/或从原始存储库中获取更改。为了做到这一点,fork包含一个引用到原始存储库,就像任何克隆通常包含一个返回其原始存储库的引用一样。

在克隆中,此引用返回原始名称​​名称,Git称之为远程。标准名称为git fetch。 Git使用它来使用git push自动从原始存储库中获取新提交,并使用git fetch --all克隆中的新提交发送到原始存储库。获取步骤将获取自上次获取或自原始克隆以来所做的提交。也就是说,这些都是他们没有的承诺。推动步骤让他们承诺他们没有。 再一次,我们看到Git拥有和关心的是提交内容。

当您使用网络服务器&#34;&#34; fork a repository&#34;网页按钮,服务器本身以一些幕后的方式记录分叉。是否以及如何检索这些记录,为每个此类克隆找到适当的服务器URL,取决于服务器。但是,如果可以全部找到它们,您只需将URL添加到某个现有克隆,每个URL一个额外的远程名称,然后使用E所有 遥控器(所有服务器克隆)进入一个克隆。

提交的真实名称是其哈希ID

在Git Universe中,ever commit具有唯一的哈希ID,与其他提交不同。两个Git存储库决定其中一个是否具有另一个不提交的提交的方式是通过比较哈希ID,因此这些必须是唯一的。没有详细介绍,这真的很有效:如果哈希匹配,两个提交是相同的,如果不匹配则不同。这意味着无论自两个存储库分歧多久以后,如果它们在某个时刻通过从另一个存储库克隆的一些提交共享某些提交,它们将共享一些提交。 1 历史在这一点上相互联系。当然,所有独特的后续提交都是唯一的,但是如果制作一个fork(即克隆)的人以某种方式将该提交转移回其他一个forks(即其他一些克隆),那么这两个克隆将共享推迟提交。

1 有一个警告:这假设没有人重写历史记录&#34;通过将每个提交复制到具有不同哈希ID的新的不同提交,然后停止使用所有原件。在这种情况下,这两个存储库不再共享任何提交,并且历史记录将不会连接。

每个克隆都是完整的,独立于所有其他克隆,除非您将它们交叉连接

虽然任何哈希值匹配的提交在所有克隆中都是相同的(根据定义),但每个克隆都独立于所有其他克隆始终。通过这种方式,我们的意思是控制该克隆的任何人都可以向其添加新的提交,或者更改其分支名称,以便这些名称引用不同的提交。例如,在我们向存储库添加提交E之后,我们可以使用git reset 删除提交E。如果我们这样做,并且不要将我们的新提交README推送到任何地方,那么其他任何人都不会看到我们做到了。我们在提交E中对D所做的更改(相对于其父A--B--C <-- master \ D <-- develop (HEAD) \ E [abandoned] )消失了:

E

这是分布式存储库的一项功能。只有在存在的情况下才存在 - 提交,但同样存在。一旦从我们的克隆向其他存储库发送提交,提交就存在于两个存储库中。它的唯一哈希ID现在都在。摆脱现在的唯一方法是确保两个存储库都有任何名称,发现提交E已更改,以便不再使用这些名称找到提交E通常我们不会尝试删除提交,除非他们没有被提供给其他人,但是,因为它确实要求转到我们提交的每个克隆,然后制作确定他们抛出这个提交的行动。因此,一旦将它们发布在通常可访问的克隆(例如Web分支)上,提交就会持续存在。

一般情况下,Git非常具有提交功能。如果我们将我们的克隆与其中的提交develop交叉连接(可从名称ourclone/develop访问)到某些其他克隆,并让其他Git进行提取,他们的Git会询问我们所拥有的所有提交,他们不会提取新提交并给它命名为git fetch。因此,来自每个分支的forkA/master将获取每个存储库中可用的每个提交,从而为我们提供一种超集克隆。

这个超级集克隆将让你做你想做的事情

一旦我们拥有一个将每个分支组合在一起的超集,我们就可以让我们的Git从每个远程跟踪名称(forkA/developforkB/master,{{1查找具有与其父提交不同的README的子提交。由于哈希ID是通用的,我们现在可以告诉,查看任何一个fork,该fork是否具有该文件的特定版本。但我们必须构建一个相当大的组合提交历史记录,以准确地看到 该文件的每个实例在实际历史记录中,这是所有提交的集合,因为文件不具备历史。

请注意,您实际上不必构建超集克隆 - 但是执行需要通过其哈希ID访问每个提交,以查看哪个版本的{{1是 in 提交,并查看提交的父级是什么,以及README的哪个版本在父级中。这意味着您必须有权访问每个fork,并查看该fork中的所有提交。您构建所有这些信息所做的工作与构建超集克隆的工作相同,因此您也可以构建超集克隆。