问题描述
如何仅将给定分支的主要修订版导出到远程git存储库到本地空间,然后对于每个导出的文件,获取该文件的提交ID?
到目前为止我尝试过的事情
执行以下操作:
git clone {gitUrl} {repoDir} --branch {branch}
然后对于每个由此导出的文件(忽略.git和内容),执行以下操作:
git rev-list -1 HEAD {file}
...通过以下方式定义以下位置标记:
虽然可行,但问题在于它太慢且效率低下。 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-list
或git 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 比较提交中出现的某些文件(A
,README.md
或任何文件的快照) main.py
及其出现在其父提交E
中的那个。如果这两个快照相同,我们希望Git将D
与D
进行比较。如果相同,Git应该继续向后工作。它应该这样做直到它在C
处的提交用尽之前,或者比较显示两个文件都不同。 1
换句话说,我们反复执行一个简单的比较操作:
- 文件 F 在提交 X 和 Y中是相同还是不同?
。答案是“是的,这是不同的”,我们让Git 停止向后浏览历史记录,并打印此时到达的提交的哈希ID。 (内部存储格式可以在提交中对文件进行重复数据删除,这非常容易。使用A
,计算会变得更加困难和幻想,但实际上却是相同的,只是逐行基础。)
但是,为了做到这一点,Git 必须具有访问权限,因为它在向后浏览历史时需要遍历每个提交。在Git中,历史记录是存储库中的一组提交。 Git必须具有历史记录才能使用历史记录。
1 Git实际使用的一个简单而便利的技巧是,当我们命中无父母(孤儿?)提交git blame
时,它可以简单地假装,在A
之前的提交完全为空。那么A
中的每个文件都是新文件,因此不同于其虚拟/伪父文件。这就是每个Git存储库都包含empty tree的原因。