记住,所有的git
分支本身都用于
跟踪一组文件的历史。因此,
每个分支实际上都是一个“跟踪分支”,因为这些分支用于跟踪文件随时间变化的历史记录?
因此,我们应该将普通的git“分支”称为“跟踪分支”,但我们没有这样做。相反,我们将它们的名称缩短为“分支”。
因此,“跟踪分支”这个术语非常令人困惑的部分原因是:对于初学者来说,它很容易意味着两种不同的东西。
在git中,“跟踪分支”的术语是“远程跟踪分支”的简称。
起初最好使用更正式的术语,直到您对这些概念更加熟悉为止。
让我们将您的问题改成这样:
什么是 "远程-跟踪分支"?
关键词在于 'Remote',所以跳到您感到困惑的部分,我将描述什么是 远程跟踪分支 以及它如何使用。
为了更好地理解git术语,包括分支和追踪,这些可能一开始非常令人困惑,我认为最容易的方法是您首先完全清楚git是什么以及其基本工作结构。如果没有像这样牢固的理解,我向您保证,您将在许多细节中迷失方向,因为git非常复杂;(翻译:许多人将其用于非常重要的事情)。
以下是简介/概述,但您可能还会发现{{link1:这篇优秀文章}}也很有帮助。
GIT是什么以及它的作用
一个git存储库就像一个家庭相册:它保存了历史快照,展示了过去时光的样子。 "快照" 是某一时刻记录下来的东西。
Git存储库不仅限于保存人类家庭照片,它可以用于记录和组织任何随着时间演变或变化的事物。
基本思想是创建一本书,以便我们可以轻松地回顾过去的时间,
当你被复杂的术语和概念所困扰时,请记住,
Git仓库首先是
快照的存储库,就像相册一样,用于存储和组织这些快照。
快照和跟踪
tracked - 跟踪一个人或动物,寻找他们曾经去过某个地方的证据(dictionary.cambridge.org)
在Git中,“您的项目”指的是文件的目录树(一个或多个文件,可能使用子目录组织成树结构),您希望保留其历史记录。
通过一个三步骤的过程,Git记录了您的项目目录树在特定时间点的“快照”。
然后,每个Git项目的快照都通过"链接"组织到前面的项目的快照中。
一个接一个地,我们可以逐个链接,向后查找任何您或您的家族的以前的快照。
例如,我们可以从今天最新的您的快照开始,然后使用链接向后查找,找到昨天或上周拍摄的您的照片,或者是您还是婴儿时的照片,或者是您的母亲等等。
这被称为“
跟踪”;在这个例子中,它追踪你的生活,或者看到你留下了什么痕迹,以及你来自哪里。
提交记录
提交记录类似于你的相册中的一页,只有一个快照,其中不仅包含了该快照的内容,还有关于该快照的相关元信息。它包括:
- 地址或固定位置,我们可以在那里找到这个提交记录,类似于页面编号。
- 项目的一个快照(文件目录树)在某个时间点的状态。
- 说明或注释,说明该快照是关于什么的。
- 该快照的日期和时间。
- 谁拍摄了该快照。
- 向后链接到先前的相关快照,例如昨天的快照或父级快照等一项或多项链接。换句话说,“链接”类似于指向其他旧照片的页码的指针,或者当我出生时指向我的直系亲属。
提交记录是组织良好的相册中最重要的部分。
随着分支和合并的时间推移,家谱不断演变
消歧义:此处的“树”不是指文件目录树,而是指随着时间推移形成的相关父子提交的家谱。
Git家谱结构模仿了我们人类的家谱树。
为了帮助您简单理解链接,我将引用以下术语:
- 一个parent-commit简称为“parent”,
- 一个child-commit简称为“child”,如果是复数则为“children”。
您应该本能地理解这一点,因为它基于生命之树:
- 一个父亲可能有一个或多个指向他们的孩子,
- 孩子总是有一个或多个指向他们的父母。
因此,除了全新的提交(可以说是“幼嫩的提交”)之外,所有提交都有一个或多个指向它们的孩子。
简单的、单一的父代链条反向链接的线状图:
(older) ... <--link1-- Commit1 <--link2-- Commit2 <--link3-- Commit3 (newest)
分支
branch - “分支”是一个活跃的开发线路。在分支上最新的提交被称为该分支的“尖端”。分支的“尖端”由一个分支头引用,随着对分支的进一步开发而向前移动。单个Git存储库可以跟踪任意数量的分支,但您的工作树仅与其中一个相关联(“当前”或“签出”分支),HEAD指向该分支。(gitglossary)
Git分支还指两件事:
- 一个名称给定的增长点(标识符)
- 链接提交之间图形中的实际分支
多个子节点指向同一个父节点,这就是Git所谓的“分支”。
注意:实际上,任何父母的任何孩子,无论是第一、第二还是第三等,都可以被视为他们自己的小分支,有着自己的生长点。因此,一个分支不一定是一个有许多节点的长物,而是一个小东西,只需从给定的父级中创建一个或多个提交即可。
一个父级的第一个孩子可能被认为是同一分支的一部分,而该父级的后续孩子通常被称为“分支”。
实际上,所有的孩子(不仅仅是第一个孩子)都从它的父级分支出来,或者你可以说是链接,但我会认为每个链接实际上是一个分支的核心部分。
正式地说,git的“分支”只是一个名称,比如'foo',给家族层次结构的特定生长点。它是所谓的“ref”的一种类型。(标签和稍后我将解释的远程也是refs。)
ref - 以refs/开头的名称(例如refs/heads/master),指向对象名称或另一个引用(后者称为符号引用)。为方便起见,当用作Git命令的参数时,有时可以缩写引用;有关详细信息,请参阅gitrevisions(7)。 引用存储在存储库中。
引用名称空间是分层的。不同的子层次结构用于不同的目的(例如,refs/heads/层次结构用于表示本地分支)。有一些不以refs/开头的特殊用途引用。最显着的例子是HEAD。(
gitglossary)
(您应该查看
.git
目录内部的文件树。这是保存git结构的地方。)
因此,例如,如果您的名字是Tom,则仅包括您快照的提交链接在一起,可能是我们命名为“Tom”的分支。
因此,虽然你可能认为树枝就是它的木材,但在Git中,分支只是给它的生长点(不包括通向它的整个木杆)起的名称。
专业的园艺师(修剪果树的人)称之为“主干”,而Git称之为主分支。
Commit1及其2个子节点的线条图(或我们所说的Git"分支"):
parent children
+-- Commit <-- Commit <-- Commit (Branch named 'Tom')
/
v
(older) ... <-- Commit1 <-- Commit (Branch named 'master')
请记住,链接仅从子级指向父级。
没有反向链接,即从旧的到新的,也就是从父级到子级的链接。
因此,父提交没有直接列出其子提交的方法,换句话说,无法列出从它派生的内容。
合并
孩子有一个或多个父母。
线条图示:带有2个父级的提交2(或我们称之为git "合并",即来自多个父级的繁殖):
parents child
... <-- Commit
v
\
(older) ... <-- Commit1 <-- Commit2
远程
这个词也有两个不同的含义:
- 一个远程仓库,以及
- 远程仓库的本地别名,即指向远程仓库的URL的名称。
远程仓库 - 用于跟踪相同项目但位于其他位置的仓库。要与远程通信,请参见获取或推送。(来源:gitglossary)
(远程仓库甚至可以是我们自己计算机上的另一个git仓库。)
实际上,每个远程名称都有两个URL,一个用于推送(即上传提交),另一个用于从远程git仓库拉取(即下载提交)。
"远程"是一个名称(标识符),它有一个关联的URL,该URL指向远程git仓库。(虽然它不止如此,但它已被描述为URL的别名。)
如果您想要拉取或推送到多个远程仓库,则可以设置多个远程。
虽然通常只有一个默认名称为“origin”的上游源(表示从哪里克隆),但可以有多个。
origin - 默认的上游存储库。大多数项目至少有一个它们跟踪的上游项目。默认情况下,使用origin进行此操作。新的上游更新将被获取到名为origin/name-of-upstream-branch的远程跟踪分支中,您可以使用git branch -r查看。(来源:gitglossary)
Origin代表你克隆仓库的位置。
那个远程仓库称为“上游”仓库,而你克隆的仓库称为“下游”仓库。
upstream - 在软件开发中,上游指向作为源代码分发的软件的原始作者或维护者的方向wikipedia
上游分支 - 默认的分支,会被合并到所讨论的分支中(或者所讨论的分支会被变基到该分支上)。
它是通过branch..remote和branch..merge进行配置的。如果A的上游分支是origin/B,有时我们会说"A正在跟踪origin/B"。(gitglossary)
这是因为大部分水通常都流向你。
不时地,您可能会将一些软件推回到上游存储库,以便它可以流向所有克隆它的人。
远程跟踪分支
远程跟踪分支首先是一个分支名称,就像任何其他分支名称一样。
它指向本地增长点,即您的本地git存储库中的最新提交。
但请注意,它实际上也指向您从中克隆提交的远程存储库中的相同提交。
远程跟踪分支 - 用于跟踪来自另一个存储库的更改的引用。它通常看起来像refs/remotes/foo/bar(表示它跟踪名为foo的远程中的名为bar的分支),并匹配配置的fetch refspec的右侧。远程跟踪分支不应包含直接修改或对其进行本地提交。(来源:
gitglossary)
假设你克隆的远程仓库只有两个提交,如下所示:
parent4 <== child-of-4
,当你克隆它时,你的本地Git仓库也有完全相同的两个提交:
parent4 <== child-of-4
。你的名为origin的远程跟踪分支现在指向
child-of-4
。
现在假设远程仓库添加了一个提交,看起来是这样的:
parent4 <== child-of-4 <== new-baby
。为了更新你的本地下游仓库,你需要获取new-baby,并将其添加到你的本地git仓库中。现在你的本地远程跟踪分支指向new-baby。你明白了吧,远程跟踪分支的概念就是为了跟踪你关心的远程分支之前的tip。
跟踪实战
首先,我们使用git开始跟踪一个文件。
![enter image description here](https://istack.dev59.com/XnfFk.webp)
以下是与文件跟踪相关的基本命令:
$ mkdir mydir && cd mydir && git init
$ git branch
$ git status -bs
$ touch foo
$ vim foo
$ git add foo; commit -m 'your description'
$ git rm --index foo; commit -m 'your description'
$ git rm foo; commit -m 'your description'
远程跟踪实现
$ git pull
关于fetch、merge等还有很多需要学习的内容,但我希望这能让你朝着正确的方向前进。
--track
选项创建一个(本地)分支,并将其中一个远程跟踪分支设置为其“upstream”。这些术语在2006年至2019年之间发生了一些演变,因此不同的人有时可能会对每个术语有不同的理解。 - torekorigin/master
:它们在您的存储库中,但它们是Git记住在origin
上看到的分支名称的方式。如果您使用更现代的术语upstream来表示您的master
已将origin/master
设置为其upstream,则可以避免所有这些术语混淆。 - torekrefs/stash
、二分查找名称和其他名称:所有这些都存储了一个哈希 ID。 - torekgit config --global push.autoSetupRemote
命令来设置自动推送远程分支。这样你就不需要太过担心了。 - Robin Bastiaan