快速便捷的Git导出和获取commit-id 长

问题描述

如何仅将给定分支的主要修订版导出到远程git存储库到本地空间,然后对于每个导出的文件获取文件的提交ID?

到目前为止我尝试过的事情

执行以下操作:

git clone {gitUrl} {repoDir} --branch {branch}

然后对于每个由此导出的文件(忽略.git和内容),执行以下操作:

git rev-list -1 HEAD {file}

...通过以下方式定义以下位置标记

  1. {gitUrl}是存储库的http URL。可以嵌入用户凭据。
  2. {repoDir}是本地系统中导出的路径。
  3. {file}是您要提取其提交ID的导出文件的完整路径。

虽然可行,但问题在于它太慢且效率低下。 git clone操作包括该分支的仓库的整个历史记录。而我们只对HEAD版本及其元数据感兴趣。

或者,我们可以执行以下导出操作:

git clone {gitUrl} {repoDir} --branch {branch} --depth 1

这效率更高,因为它只是下拉了HEAD版本。但是问题在于,随后的git rev-list -1 HEAD {file}命令将返回整个HEAD的提交ID,而不是文件的提交ID。

我可以吃我的蛋糕吗?

解决方法

我可以吃我的蛋糕吗?

简短的回答是“否”。

从技术上讲,HEAD提交中每个文件的提交ID是您通过git rev-parse HEAD(或更长但等效的git rev-list命令获得的哈希ID您正在使用)。这是因为每次提交都包含Git知道的每个文件的完整快照。

使用git rev-listgit log或在每一行一个文件中使用git blame命令向后回顾历史时得到的不是提交有问题的文件的哈希ID,因为这很简单。相反,它是某些较早提交的提交哈希ID,其中包含相同文件,或者对于git blame相同行。 / p>

也就是说,假设我们在Git存储库中有一个简单的线性历史记录,其中只有五个提交。我们可以这样绘制这五个提交:

A <-B <-C <-D <-E   <--master

其中每个大写字母代表一个实际的提交哈希ID。分支名称(在这种情况下为master)用于让我们找到提交E的实际哈希ID,因为它看起来是随机的,否则很难或有时无法找到。

提交E当然包含每个文件的完整快照,其格式与我们(或任何人)提交E时的格式相同。它还包含较早提交D的哈希ID。 Git将D称为提交E父级

但是提交D还具有每个文件的完整快照,格式与某人创建D时的格式相同,并具有指向其父{{1 }}。在整个历史记录中都会重复C等等,以此类推(直到我们点击C时结束,而没有父提交)。

在这种情况下,我们想要的是让Git 比较提交中出现的某些文件(AREADME.md或任何文件的快照) main.py及其出现在其父提交E中的那个。如果这两个快照相同,我们希望Git将DD进行比较。如果相同,Git应该继续向后工作。它应该这样做直到它在C处的提交用尽之前,或者比较显示两个文件都不同。 1

换句话说,我们反复执行一个简单的比较操作:

  • 文件 F 在提交 X Y中是相同还是不同?
每个父/子提交对

。答案是“是的,这是不同的”,我们让Git 停止向后浏览历史记录,并打印此时到达的提交的哈希ID。 (内部存储格式可以在提交中对文件进行重复数据删除,这非常容易。使用A,计算会变得更加困难和幻想,但实际上却是相同的,只是逐行基础。)

但是,为了做到这一点,Git 必须具有访问权限,因为它在向后浏览历史时需要遍历每个提交。在Git中,历史记录是存储库中的一组提交。 Git必须具有历史记录才能使用历史记录。


1 Git实际使用的一个简单而便利的技巧是,当我们命中无父母(孤儿?)提交git blame时,它可以简单地假装,在A之前的提交完全为空。那么A中的每个文件都是新文件,因此不同于其虚拟/伪父文件。这就是每个Git存储库都包含empty tree的原因。