git Fetch数据存储在哪里?

13

我是git的新手,正在尝试理解相关概念。

refspec - 据我所知,将服务器分支映射到“本地”目标分支。

我写“本地”,因为如果我们执行'git fetch',它们不会与我们的工作副本或暂存区合并,而是保存在其他地方。

那么我的问题是

A)它们存储在.git/refs/remotes/origin/(branches)中吗?

B)如果是,.git/refs/remotes/origin/(branch)的内容是否是指向服务器上更改位置的参考/ID?

在.git/refs/remotes/origin/的一个分支中,我发现了这个:761db53af177ecfd9c9b14511360537e041ebed7

C)当我们提交时,更改保存在哪里?

它们存储在.git/objects中吗?

2个回答

7
这些问题已经在其他地方逐个回答过了,但我会提供一个简短的综合回答:
refspec - 就我所知,将服务器分支映射到“本地”目标分支
这只是一种效果,而不是定义。
Refspec 的定义只是一对引用名称,由冒号“:”分隔,并带有可选的前导加号“+”。冒号左侧的引用名称是源,右侧的名称是目标。如果存在前导加号,则 refspec 表示 Git 应该执行“强制更新”,即使它不是快进(分支引用)或自然被禁止(对于标签),也要更新引用。
Refspecs被用于git fetchgit push。在不同的命令中,省略其中一个部分会产生不同的效果,因此最好使用两边都完整的refspecs。当与git fetch一起使用时,源确实是服务器的引用(通常是分支名称,但您可以复制标签、注释或服务器公开的任何其他引用,并且默认情况下,服务器公开所有内容)。目的地是您自己的本地引用,同样通常是分支名称。
你的第一个问题:

A) 它们存储在.git/refs/remotes/origin/(branches)吗?

默认情况下,是的。但请注意几个注意事项:
  • 要查找.git目录,请使用git rev-parse --show-toplevelgit rev-parse --show-cdup(如果您在子目录中)。
  • 参考名称可能会被压缩,在这种情况下,它们不会存储在自己的单独文件中。
  • Git正在(内部)发展可插拔的后端用于ref-name,因此即使上述内容也可能会更改:为了从脚本解析或更新ref-name,您应该使用Git的“plumbing”命令,即git rev-parsegit symbolic-refgit update-ref

以上限定语中的“默认情况下”是因为目标名称实际上是一个配置项。对于名为origin的远程主机,git fetch默认使用配置的remote.origin.fetch值:

$ cd [path to git repo for git]
$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$ cd [path to git repo for FreeBSD]
$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
+refs/notes/*:refs/notes/origin/*
$ 

如上所示,您可以为任何给定的远程配置多个fetch配置。

(对于名为$rem的远程,使用git config --get-all remote.$rem.fetch查看其默认提取refspec。)

如上所示,提取refspec可能包含通配符*字符。这些字符的工作方式类似于shell(sh、bash、zsh等)的“glob”字符,但在较早的Git2版本中,它们仅限于出现在斜杠后面/(例如,refs/heads/pr*将被禁止),当它们出现在目标侧时,它们只是扩展回匹配源侧的内容,因此必须配对使用。

B)如果是,每个.git/refs/remotes/origin/(branch)的内容是否是对更改所在位置的引用/ID?

有点像:它是一个对象标识符。(这个问题的确切形式暗示了一个错误的假设,我们一会儿就会解决。)

因为refs/remotes/origin/$branch是一个远程跟踪分支名称(因此是refs/heads/命名空间分支名称的副本),它实际上必须指向3提交对象。请注意,名称在refs/中的位置确定了引用类型。引用类型意味着对象类型:大多数名称通常应该指向提交对象,但标签名称可以指向四种基本对象类型之一。(这四种类型是提交blobtag或“注释标签”;标签名称通常应直接指向提交或注释标签对象。提交指向父提交和一个树;树指向blob和其他树;blob包含文件内容。另请参见问题C的答案。)

C)当我们进行提交时,更改保存在哪里?

这就是你偏离正轨进入荒野的地方:Git保存快照而不是更改。 但你大多数时间都在正确的区域!

一张图片胜过千言万语,所以我会包含Pro Git书的章节链接
引用:
它们是存储在.git/objects中的吗?
是的,这就是Git存储其"对象文件"的地方。新提交意味着新的对象,新对象进入该目录(实际文件名是complexificationified4,以使Git在Linux盒子上运行更快,其中"fat"目录很慢)。如上所述,新提交指向一个树——通常是新的树对象,而不是某个现有的树对象——树提供了从合理的用户文件名(和文件模式,特别是执行位)到Git blob对象名称的映射。树和blob对象也存储在.git/objects中。

然而,这样会增加复杂性,对象可能会被“打包”到一个“pack文件”中。(在这一点上,Git开始进行增量压缩,就像其他版本控制系统一样,但有一个显著的转折点,即增量压缩不需要针对“相同”的文件的先前版本,甚至不需要针对任何文件。实际上,目前选择增量链的启发式方法是通过文件名和大小关联,但原则上,如果这样做效果好的话,我们可以将一个文件与树进行压缩,反之亦然。)


1“Short”指的是“写作时间”,而不是“回答长度”。:-) 如果我花更长时间,我可以写出更短的答案…… 2大约在Git 2.5左右,但我没有时间查找限制通配符放置的确切版本。 3这里的“指向”一词是指“包含ID”,并暗示我们或Git可以跟随此ID找到对象本身,就像跟随一个指向箭头一样:这条路通向对象。 4非英语母语者请原谅:这不是一个真正的单词,而是将“复杂”和“复杂化”混合成的一个新词,并加上副词后缀“-ify”两次,用胶水、锉刀和砂纸粘合和打磨而成,以增加复杂性。 :-)

0

首先考虑提交历史记录,包括最初、最后和除此之外的所有内容。在Git中,所有的东西都可以归结为提交名称及其祖先。每当你看到一个引用名称时,你需要做的第一件事就是将其转换为提交ID,因为这就是Git所做的。Git中的所有内容都存储在对象数据库中。"暂存区"实际上并不存在,它只是对象数据库中的一种概念状态(即在某个时间点上添加到其中、提取到其中或推送到其中的东西),以及索引。它们可能尚未被实际提交所引用。但不要纠缠于抽象概念,Git是具体的。学习操作的实际含义,它们的目的不是为了实现某种抽象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接