这些问题已经在其他地方逐个回答过了,但我会提供一个简短的综合回答:
refspec - 就我所知,将服务器分支映射到“本地”目标分支
这只是一种效果,而不是定义。
Refspec 的定义只是一对引用名称,由冒号“:”分隔,并带有可选的前导加号“+”。冒号左侧的引用名称是源,右侧的名称是目标。如果存在前导加号,则 refspec 表示 Git 应该执行“强制更新”,即使它不是快进(分支引用)或自然被禁止(对于标签),也要更新引用。
Refspecs被用于
git fetch
和
git push
。在不同的命令中,省略其中一个部分会产生不同的效果,因此最好使用两边都完整的refspecs。当与
git fetch
一起使用时,源确实是服务器的引用(通常是分支名称,但您可以复制标签、注释或服务器公开的任何其他引用,并且默认情况下,服务器公开所有内容)。目的地是您自己的本地引用,同样通常是分支名称。
你的第一个问题:
A) 它们存储在.git/refs/remotes/origin/(branches)吗?
默认情况下,是的。但请注意几个注意事项:
- 要查找
.git
目录,请使用git rev-parse --show-toplevel
或git rev-parse --show-cdup
(如果您在子目录中)。
- 参考名称可能会被压缩,在这种情况下,它们不会存储在自己的单独文件中。
- Git正在(内部)发展可插拔的后端用于ref-name,因此即使上述内容也可能会更改:为了从脚本解析或更新ref-name,您应该使用Git的“plumbing”命令,即
git rev-parse
,git symbolic-ref
和git 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/
中的位置确定了
引用类型。引用类型意味着对象类型:大多数名称通常应该指向提交对象,但标签名称可以指向四种基本对象类型之一。(这四种类型是
提交、
树、
blob和
tag或“注释标签”;标签名称通常应直接指向提交或注释标签对象。提交指向父提交和一个树;树指向blob和其他树;blob包含文件内容。另请参见问题C的答案。)
C)当我们进行提交时,更改保存在哪里?
这就是你偏离正轨进入荒野的地方:Git保存快照而不是更改。 但你大多数时间都在正确的区域!
一张图片胜过千言万语,所以我会包含
Pro Git书的章节链接。
引用:
它们是存储在.git/objects中的吗?
是的,这就是Git存储其"对象文件"的地方。新提交意味着新的对象,新对象进入该目录(实际文件名是complexificationified
4,以使Git在Linux盒子上运行更快,其中"fat"目录很慢)。如上所述,新提交指向一个树——通常是新的树对象,而不是某个现有的树对象——树提供了从合理的用户文件名(和文件模式,特别是执行位)到Git blob对象名称的映射。树和blob对象也存储在.git/objects中。
然而,这样会增加复杂性,对象可能会被“打包”到一个“pack文件”中。(在这一点上,Git开始进行增量压缩,就像其他版本控制系统一样,但有一个显著的转折点,即增量压缩不需要针对“相同”的文件的先前版本,甚至不需要针对任何文件。实际上,目前选择增量链的启发式方法是通过文件名和大小关联,但原则上,如果这样做效果好的话,我们可以将一个文件与树进行压缩,反之亦然。)
1“Short”指的是“写作时间”,而不是“回答长度”。:-) 如果我花更长时间,我可以写出更短的答案……
2大约在Git 2.5左右,但我没有时间查找限制通配符放置的确切版本。
3这里的“指向”一词是指“包含ID”,并暗示我们或Git可以跟随此ID找到对象本身,就像跟随一个指向箭头一样:这条路通向对象。
4非英语母语者请原谅:这不是一个真正的单词,而是将“复杂”和“复杂化”混合成的一个新词,并加上副词后缀“-ify”两次,用胶水、锉刀和砂纸粘合和打磨而成,以增加复杂性。 :-)