有人能解释一下应用于git的“跟踪分支”吗?

以下是来自git-scm.com的定义:

Git中的“跟踪分支”是一个本地分支 与远程连接的分支 分支。当你用力拉它的时候 分支,它自动推和 拉到它所在的远端分支 与。 如果你总是从 相同的上游分支进入新的 布兰奇,如果你不想用 "git pull"。

不幸的是,作为git的新手和来自SVN的新手,这个定义对我来说完全没有意义。

我阅读“Git实用指南”(伟大的书,顺便),和他们似乎表明,跟踪分支是一件好事,在创建你的第一个远程(起源,在这种情况下),你应该设置主分支跟踪分支,但不幸的是不包括为什么跟踪分支是一件好事或得到什么好处通过设置你的主分支是一个跟踪分支起源库。

有人能(用英语)给我开导一下吗?


当前回答

这就是我如何添加一个跟踪分支,这样我就可以从它拉到我的新分支:

git branch --set-upstream-to origin/Development new-branch

其他回答

ProGit的书有一个很好的解释:

跟踪分支

从远程分支签出本地分支会自动创建所谓的跟踪分支。跟踪分支是与远程分支有直接关系的本地分支。如果你在跟踪分支上,输入git push, git会自动知道要推送到哪个服务器和哪个分支。此外,在其中一个分支上运行git pull会获取所有远程引用,然后自动合并到相应的远程分支中。

When you clone a repository, it generally automatically creates a master branch that tracks origin/master. That’s why git push and git pull work out of the box with no other arguments. However, you can set up other tracking branches if you wish — ones that don’t track branches on origin and don’t track the master branch. The simple case is the example you just saw, running git checkout -b [branch] [remotename]/[branch]. If you have Git version 1.6.2 or later, you can also use the --track shorthand:

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "serverfix"

要设置一个与远程分支名称不同的本地分支,您可以轻松地使用第一个版本的不同本地分支名称:

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "sf"

现在,您的本地分支sf将自动推入和拉入origin/serverfix。

奖励:额外的git状态信息

有了跟踪分支,git状态会告诉你你落后于跟踪分支多远——这有助于提醒你还没有推送你的更改!它是这样的:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

or

$ git status
On branch dev
Your branch and 'origin/dev' have diverged,
and have 3 and 1 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

记住,所有git分支本身都用于跟踪一组文件的历史记录。因此,每个分支实际上不是一个“跟踪分支”吗?因为这就是这些分支的用途:随着时间的推移跟踪文件的历史记录。

因此,我们可能应该称正常的git为“分支”,“跟踪分支”,但我们没有这样做。相反,我们把它们的名字简称为“分支”。


这就是为什么术语“跟踪分支”如此令人困惑的部分原因:对于外行来说,它很容易意味着两种不同的东西。

在git中,术语“跟踪分支”是更完整术语“远程跟踪分支”的缩写。

如果一开始用更正式的术语代替,可能会更好,直到你对这些概念更熟悉为止。


让我们把你的问题改成这样:

什么是“远程跟踪分支”?

这里的关键词是“远程”,所以跳过你感到困惑的地方,我将描述什么是远程跟踪分支以及如何使用它。


为了更好地理解git的术语,包括分支和跟踪,这在一开始可能会让人很困惑,我认为如果你先弄清楚git是什么以及它如何工作的基本结构,这是最容易的。如果没有这样的扎实理解,我保证你会迷失在许多细节中,因为git非常复杂;(翻译:很多人用它来做非常重要的事情)。

以下是一个介绍/概述,但您可能会发现这篇优秀的文章也有丰富的信息。


git是什么,它是干什么用的

git存储库就像一个家庭相册:它保存了历史快照,显示了过去的情况。“快照”是在特定时刻对某件事的记录。

git存储库并不局限于保存人类家庭照片。相反,它可以用来记录和组织任何随着时间发展或变化的东西。

基本的想法是创造一本书,这样我们就可以很容易地回顾过去,

将过去的时间与现在或其他时间的时刻进行比较 重现过去。


当您陷入复杂性和术语的泥潭时,请记住git存储库首先是一个快照存储库,就像相册一样,它用于存储和组织这些快照。


快照和跟踪

追踪——通过寻找某人或动物去过某地的证据来跟踪他们(dictionary.cambridge.org)

在git中,“your project”指的是一个文件目录树(一个或多个,可能使用子目录组织成树结构),您希望保留其历史记录。

Git通过3个步骤,在给定时刻记录项目目录树的“快照”。

你的项目的每个git快照,然后由“链接”组织指向你的项目以前的快照。

一个接一个,一个接一个,我们可以回顾过去,找到你以前的任何快照,或你的遗产。

例如,我们可以从你今天最近的快照开始,然后使用一个链接,回溯到你昨天或上周拍摄的照片,或者你还是个婴儿的时候,甚至你的母亲是谁,等等。

这被称为“跟踪;在这个例子中,它是跟踪你的生活,或者看到你在哪里留下了足迹,以及你从哪里来。


提交

提交类似于带有单个快照的相册中的一页,因为它不仅包含快照,还包含关于该快照的相关元信息。它包括:

an address or fixed place where we can find this commit, similar to its page number, one snapshot of your project (of your file directory tree) at a given moment in time, a caption or comment saying what the snapshot is of, or for, the date and time of that snapshot, who took the snapshot, and finally, one, or more, links backwards in time to previous, related snapshots like to yesterday's snapshot, or to our parent or parents. In other words "links" are similar to pointers to the page numbers of other, older photos of myself, or when I am born to my immediate parents.

提交是一个组织良好的相册中最重要的部分。


随着时间的推移,家族树有分支和合并

消歧:这里的“树”指的不是上面使用的文件目录树,而是一段时间内相关的父和子提交的家族树。

git的家谱结构是以我们自己的人类家谱为蓝本的。

为了更简单地理解链接,我将参考以下内容:

一个简单的“父母”提交,和 child-commit是简单的“child”或“children”的复数形式。

你应该本能地理解这一点,因为它是基于生命之树:

父母可能有一个或多个孩子指向过去的他们,而且 孩子总是有一个或多个他们指向的父母。

因此,除了全新的提交(可以称为“少年提交”)外,所有的提交都有一个或多个子提交指向它们。

如果没有孩子指向父母,那么这个提交只是一个“成长提示”,或者下一个孩子将从哪里出生。 只有一个子指向一个父,这只是一个简单的单亲<-- -子关系。

一个简单的,在时间上向后连接的单一父链的折线图:

(older) ... <--link1-- Commit1 <--link2-- Commit2 <--link3-- Commit3 (newest)

分支机构

分支——“分支”是一条活跃的发展路线。分支上最近的提交被称为该分支的尖端。 分支的尖端由一个移动的分支头引用 在分支上完成额外的开发时向前。一个Git 存储库可以跟踪任意数量的分支,但是您的 工作树只与其中一个(“当前”或 "checked out"分支),HEAD指向该分支。(gitglossary)

git分支还指两个东西:

生长尖端的名称(标识符)和 提交之间链接图中的实际分支。

超过一个子指向>父,这就是git所说的“分支”。

注:在现实中,任何父母的任何孩子,无论是第一个、第二个还是第三个等等,都可以被视为自己的小分枝,有自己的生长尖端。所以分支不一定是一个有很多节点的长东西,而是一个小东西,由给定父节点的一个或多个提交创建。

父结点的第一个子结点可以说是同一分支的一部分,而该父结点的后续子结点通常被称为“分支”。

实际上,所有子分支(不仅仅是第一个)都来自它的父分支,或者你可以说link,但我认为每个链接实际上都是分支的核心部分。

从形式上讲,git“分支”只是一个名称,例如“foo”,用于指定一个家族层次结构的特定生长尖端。这是他们所谓的“裁判”的一种。(标签和遥控器也是参考资料,我稍后会解释。)

ref - A name that begins with refs/ (e.g. refs/heads/master) that points to an object name or another ref (the latter is called a symbolic ref). For convenience, a ref can sometimes be abbreviated when used as an argument to a Git command; see gitrevisions(7) for details. Refs are stored in the repository. The ref namespace is hierarchical. Different subhierarchies are used for different purposes (e.g. the refs/heads/ hierarchy is used to represent local branches). There are a few special-purpose refs that do not begin with refs/. The most notable example is 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')    

记住,链接只能从子节点指向父节点。 没有指向另一个方向的链接,即从旧到新,也就是从父母到孩子。

因此,父提交没有直接的方法来列出它的子提交,或者换句话说,它派生了什么。


合并

孩子有一个或多个父母。

如果只有一个父节点,这就是一个简单的parent <——child提交。 如果有多个父节点,这就是git所说的“合并”。 每个孩子可以同时指向不止一个父母,就像有母亲和父亲一样,而不仅仅是母亲。

与2个父母(或我们称之为git“合并”,即从多个父母生育)的Commit2折线图:

                parents     child

           ... <-- Commit
                        v
                         \
(older) ... <-- Commit1 <-- Commit2  

远程

这个词也有两种不同的意思:

远程存储库和 远程存储库的本地别名,即使用URL指向远程存储库的名称。

远程存储库——用于跟踪相同项目但驻留在其他地方的存储库。若要与遥控器通信,请参见 取或推。(gitglossary)

(远程存储库甚至可以是我们自己计算机上的另一个git存储库。) 实际上,每个远程名称都有两个url,一个用于从远程git存储库中推送(即上传提交),另一个用于拉取(即下载提交)。

“remote”是一个名称(一个标识符),它有一个指向远程git存储库的关联URL。(它被描述为URL的别名,尽管它不止于此。)

如果您希望拉入或推入多个远程存储库,则可以设置多个远程存储库。

尽管通常只有一个,而且它的默认名称是“origin”(意思是克隆的上游源)。

origin—默认的上游存储库。大多数项目至少有一个他们跟踪的上游项目。默认使用origin 为了这个目的。新的上游更新将被取入 名为origin/name-of-upstream-branch的远程跟踪分支,可以使用git branch -r查看。(gitglossary)

原点表示从哪里克隆存储库。 该远程存储库称为“上游”存储库,克隆的存储库称为“下游”存储库。

上游——在软件开发中,上游指的是面向作为源代码维基百科发布的软件的原始作者或维护者的方向

上游分支——被合并到有问题的分支中的默认分支(或者被重基于的分支)。 它通过branch..remote和branch..merge进行配置。如果A的上游分支是原点/B,有时我们说“A正在跟踪原点/B”。(gitglossary)

这是因为大部分的水一般都流向你。 您可能会不时地将一些软件推回上游存储库,这样它就可以流向所有克隆它的人。

远程跟踪分支机构

首先是远程跟踪分支,只是一个分支名称,就像任何其他分支名称一样。

它指向本地增长提示,即最近在本地git存储库中的提交。

但是请注意,它还有效地指向远程存储库中的同一提交,您从其中克隆了该提交。

远程跟踪分支——用于跟踪来自另一个存储库的更改的引用。它通常看起来像refs/remotes/foo/bar (表示它跟踪名为foo的远程对象中名为bar的分支), 并匹配已配置的获取refspec的右侧。远程跟踪分支不应该包含直接的修改 本地提交。(gitglossary)

假设您克隆的远程只有2次提交,就像这样:parent4 <== child-of-4,然后您克隆它,现在您的本地git存储库有相同的两次提交:parent4 <== child-of-4。 名为origin的远程跟踪分支现在指向child-of-4。

现在假设向远程添加了一个提交,它看起来像这样:parent4 <== child-of-4 <== new-baby。要更新本地下游存储库,您需要获取new-baby,并将其添加到本地git存储库。现在你的本地远程跟踪分支指向新生儿。您应该明白了,远程跟踪分支的概念就是简单地跟踪您所关心的远程分支的前端。


实时跟踪

首先,我们开始用git跟踪一个文件。

下面是文件跟踪的基本命令:

$ mkdir mydir &&  cd mydir &&  git init         # create a new git repository

$ git branch                                    # this initially reports no branches
                                                #  (IMHO this is a bug!)

$ git status -bs   # -b = branch; -s = short    # master branch is empty
## No commits yet on master

# ...
$ touch foo                                     # create a new file

$ vim foo                                       # modify it (OPTIONAL)


$ git add         foo; commit -m 'your description'  # start tracking foo 
$ git rm  --index foo; commit -m 'your description'  # stop  tracking foo 
$ git rm          foo; commit -m 'your description'  # stop  tracking foo 
                                                     #   & also delete foo

远程跟踪

$ git pull    # Essentially does:  get fetch; git merge    # to update our clone

关于取回、合并等还有很多东西要学,但我希望这能让你走在正确的方向上。

以下是我个人关于GIT跟踪分支的学习笔记,希望对以后的访问者有所帮助:


跟踪分支和“git取回”:

这就是我如何添加一个跟踪分支,这样我就可以从它拉到我的新分支:

git branch --set-upstream-to origin/Development new-branch

Pro Go书中提到:

跟踪分支是与远程分支有直接关系的本地分支

不完全是。SO问题“很难理解git-fetch”包括:

没有本地跟踪分支的概念,只有远程跟踪分支。 因此,origin/master是在origin repo中对master的远程跟踪分支。


注意,Git 2.37 (Q3 2022)允许你自动设置远程跟踪分支,包括:

git config --global push.autoSetupRemote true

但实际上,一旦你建立了上游分支关系:

一个地方分支像师父 还有一个远程跟踪分支,比如origin/master

你可以用git branch -avv列出它们。

然后,您可以将master视为一个本地跟踪分支:它跟踪远程跟踪分支原点/master,而master又跟踪上游回购原点的主分支。

换句话说:“远程跟踪分支”中的“远程”意味着远程分支的本地副本(跟踪),以记住最后获取的内容。 Michael Freidgeim在评论中补充道:

术语“远程跟踪分支”令人困惑。 更准确的说法是: “位于本地的远程跟踪分支”。 否则,有人可能会解释为“远程跟踪分支”位于源服务器上。