我刚刚开始使用Git,我在不同的分支之间感到很困惑。任何人都可以帮我弄清楚以下分支类型是什么?
他们之间有什么区别?他们如何相互合作?
我想,快速演示代码非常有用。
答案 0 :(得分:164)
这是一个很长的答案。
如果您正在协作使用Git,则可能需要将提交与其他计算机或位置同步。每个机器或位置在Git的术语中称为远程,并且每个机器或位置可以具有一个或多个分支。大多数情况下,您只有一个名为origin
的人。要列出所有遥控器,请运行git remote
:
$ git remote
bitbucket
origin
通过运行git remote -v
:
$ git remote -v
bitbucket git@bitbucket.org:flimm/example.git (fetch)
bitbucket git@bitbucket.org:flimm/example.git (push)
origin git@github.com:Flimm/example.git (fetch)
origin git@github.com:Flimm/example.git (push)
每个遥控器都有git/refs/remotes/
下的目录:
$ ls -F .git/refs/remotes/
bitbucket/ origin/
TLDR:在您的本地计算机上,您有三种类型的分支:本地非跟踪分支,本地跟踪分支和远程跟踪分支。在远程计算机上,您只有一种分支。
您可以通过运行git branch
:
$ git branch
master
new-feature
每个本地分支都有.git/refs/heads/
下的文件:
$ ls -F .git/refs/heads/
master new-feature
您的计算机上有两种类型的本地分支:非跟踪本地分支和跟踪本地分支。
非跟踪本地分支不与任何其他分支相关联。您可以通过运行git branch <branchname>
来创建一个。
跟踪本地分支与另一个分支相关联,通常是远程跟踪分支。您可以通过运行git branch --track <branchname> [<start-point>]
来创建一个。
您可以使用git branch -vv
查看哪个本地分支机构正在跟踪分支:
$ git branch -vv
master b31f87c85 [origin/master] Example commit message
new-feature b760e04ed Another example commit message
从此命令的输出中,您可以看到本地分支master
正在跟踪远程跟踪分支origin/master
,而本地分支new-feature
未跟踪任何内容
查看哪些分支跟踪分支的另一种方法是查看.git/config
。
跟踪本地分支很有用。它们允许您运行git pull
和git push
,而无需指定要使用的上游分支。如果分支没有设置为跟踪另一个分支,那么您将收到类似这样的错误:
$ git checkout new-feature
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream new-feature <remote>/<branch>
您可以通过运行git branch -r
来查看计算机上所有远程跟踪分支的列表:
$ git branch -r
bitbucket/master
origin/master
origin/new-branch
每个远程跟踪分支都有.git/refs/<remote>/
下的文件:
$ tree -F .git/refs/remotes/
.git/refs/remotes/
├── bitbucket/
│ └── master
└── origin/
├── master
└── new-branch
将远程跟踪分支视为远程计算机所包含的本地缓存。您可以使用git fetch
git pull
在幕后使用的git remote show <remote>
来更新远程跟踪分支。
即使远程跟踪分支的所有数据都存储在您的计算机本地(如缓存),它仍然永远不会被称为本地分支。 (至少,我不会这么称呼它!)它只是被称为远程跟踪分支。
您可以通过运行$ git remote show origin
* remote origin
Fetch URL: git@github.com:Flimm/example.git
Push URL: git@github.com:Flimm/example.git
HEAD branch: master
Remote branches:
io-socket-ip new (next fetch will store in remotes/origin)
master tracked
new-branch tracked
Local ref configured for 'git pull':
master merges with remote master
new-branch merges with remote new-branch
Local ref configured for 'git push':
master pushes to master (up to date)
new-branch pushes to new-branch (fast-forwardable)
来查看所有远程分支(即远程计算机上的分支):
git remote
此git fetch
命令通过网络查询远程计算机的分支。它不会更新本地计算机上的远程跟踪分支,请使用git pull
或refs/heads/
。
从输出中,您可以通过查看标题&#34; Remote branches&#34;来查看远程计算机上存在的所有分支。 (忽略标记为&#34的行;陈旧&#34;)。
如果您可以登录到远程计算机并在文件系统中找到存储库,则可以查看git branch -d <branchname>
下的所有分支。
要安全地删除本地分支,无论是跟踪还是非跟踪:
git branch -D <branchname>
要强制删除本地分支,无论是跟踪还是非跟踪:
git branch -rd <remote>/<branchname>
删除远程跟踪分支:
git branch <branchname> [<start-point>]
创建新的本地非跟踪分支:
<start-point>
要创建新的本地跟踪分支:(请注意,如果指定了origin/foobar
并且是--track
之类的远程跟踪分支,则会自动包含git branch --track <branchname> [<start-point]
标记)
git branch --track hello-kitty origin/hello-kitty
示例:
git push --delete <remote> <branchname>
删除远程计算机上的分支:
git remote prune <remote>
删除所有过时的远程跟踪分支,即远程计算机上相应分支不再存在的位置:
<remote>/<branch>
您可能已经注意到,在某些命令中,您使用<remote> <branch>
和其他命令git branch origin/hello-kitty
。示例:git push --delete origin hello-kitty
和{{1}}。
它可能看似随意,但有一种简单的方法可以记住何时使用斜杠以及何时使用空格。当您使用斜杠时,您指的是您自己机器上的远程跟踪分支,而当您使用空格时,您实际上正在处理某个分支上的分支。通过网络远程机器。
答案 1 :(得分:93)
本地分支是只有您(本地用户)才能看到的分支。它仅存在于您的本地计算机上。
git branch myNewBranch # Create local branch named "myNewBranch"
远程分支是远程位置的分支(大多数情况下为origin
)。您可以将新创建的本地分支myNewBranch
推送到origin
。现在其他用户可以跟踪它。
git push -u origin myNewBranch # Pushes your newly created local branch "myNewBranch"
# to the remote "origin".
# So now a new branch named "myNewBranch" is
# created on the remote machine named "origin"
远程跟踪分支是远程分支的本地副本。使用上述命令将myNewBranch
推送到origin
时,会在您的计算机上创建名为origin/myNewBranch
的远程跟踪分支。此远程跟踪分支跟踪myNewBranch
上的远程分支origin
。您可以使用git fetch
或git pull
更新远程跟踪分支以与远程分支同步。
git pull origin myNewBranch # Pulls new commits from branch "myNewBranch"
# on remote "origin" into remote tracking
# branch on your machine "origin/myNewBranch".
# Here "origin/myNewBranch" is your copy of
# "myNewBranch" on "origin"
本地跟踪分支是跟踪另一个分支的本地分支。这样您就可以向/从另一个分支推送/拉出提交。在大多数情况下,本地跟踪分支跟踪远程跟踪分支。当您使用带有origin
选项的git push command
将本地分支推送到-u
时(如上所示),您可以设置本地分支myNewBranch
来跟踪远程跟踪分支origin/myNewBranch
。这需要使用git push
和git pull
而不指定上游推送或拉出。
git checkout myNewBranch # Switch to myNewBranch
git pull # Updates remote tracking branch "origin/myNewBranch"
# to be in sync with the remote branch "myNewBranch"
# on "origin".
# Pulls these new commits from "origin/myNewBranch"
# to local branch "myNewBranch which you just switched to.
答案 2 :(得分:11)
本地分支机构:
您的计算机上的一个分支,您可以在其中工作并添加提交。您可以使用git branch
列出这些分支。
本地分支(带跟踪):
配置为对应于远程分支的普通本地分支。这具有git pull
和git push
的能力,而无需指定存储库和分支名称。当您的分支位于遥控器的前方或后方时,跟踪还会导致git status
通知您。
远程分支:
只是远程存储库上的分支 - 通常位于服务器上,例如GitHub等。
远程跟踪分支:
远程分支的本地副本。永远不应该编辑该分支。其目的是跟踪远程分支的当前状态。可以使用git branch -r
查看远程跟踪分支,通常看起来像origin/master
(repo name后跟斜杠后跟分支名称)。运行git fetch
将更新远程跟踪分支以反映相应远程分支的状态。
git branch -avv
是我个人最喜欢的,可以快速浏览我的机器上哪些分支,远程哪些分支以及每个分支的最新提交。 -a
部分指定应显示所有分支(远程和本地)。最后的v
代表详细(它显示了最后一次提交哈希和消息)。感谢@Flimm指出第二个v
添加了有关哪个本地分支正在跟踪哪个遥控器的信息。
答案 3 :(得分:2)
TL;DR - 井井有条,您可以直接跳到需要了解的内容。
以下是我将要介绍的内容:
local 分支是我们本地存储库中的一个名称,它指的是此处的头部。
远程分支是远程存储库上的一个名称,它指的是那里的头。
一个简单的分支是一个引用一件事的本地名称:
tracking-branch 是引用两件事的本地名称:
跟踪分支有两种:
local - 分支指向本地头的位置。
这些被称为local-tracking-branchs。 (更多内容见下文。)
remote - 分支指向远程头的本地副本。
这些被称为远程-tracking-branches。 (更多内容见下文。)
以下是 4 种类型的分支、我们看到它们的位置以及它们的映射方式:
WHERE ---BRANCH TYPE-------- --REFERENCE TARGETS-------
--------------------------------------------------------------
Remote simple branch -----------> remote head (a commit ID)
--------------------------------------------------------------
Local simple branch -----------> local head (a commit ID)
Local local tracking-branch --> local head (a commit ID1)
--> Remote-name/branch-name
Local remote tracking-branch --> local head (a commit ID2)
--> Remote-name/branch-name
--------------------------------------------------------------
术语远程和分支似乎超载了。
并且短语tracking branch 尤其令人困惑,因为它与tracking-branch 并不是一回事。
'a snapshot' - A recording of the state of one or more files
and their contents at a given moment in time.
'a commit' - A container holding one snapshot, the date and
time it was recorded, who recorded it, and a
comment to say what it's all about.
'a repository' - A repository of commits, organized so we can
look thru them, going backwards in time.
Much like photos added in sequence to a photo
album book, to record our own history, each commit
contains a snapshot of the exact state of our
project at a given moment in time.
It is used to be able to look backwards in time to
how it was at any recorded previous time.
'Remote' - (Upper case) Short for 'a named remote repository'
(of commits, of snapshots)
'remote' - (Lower case) Located on another git repository
'local' - Located on your local git repository
'a head' - A specific young commit, with no children yet of
it's own (i.e. no other commits yet pointing to it),
but which may link backwards in time to one or more
of it's natural parents.
Also called a growing tip.
Initially set to a <start-point>.
'a branch' - A symbolic name (i.e. an identifier) pointing
to one specific head, and possibly, depending on
the branch type, also pointing to a remote branch.
The term 'branch' can also refer to a specific
linked list of multiple commits (plural), starting
from the growing tip (or most recent baby), and
linking offspring to their parent(s) backwards in
time.
'tracks' - As we move forward, tracks are what we leave behind.
'tracked' - To be followed, as in, to come afterwards, or after
the fact, by way of the evidence left behind, of the
a state of being of the thing being tracked, as it
moves forwards in time.
'tracking' - The process of capturing and organizing snapshots of
our project so we can later look backwards in time
to find how it previously was.
'tracking-branch' - This term is somewhat redundant, and confusing,
but does have a specific, important meaning.
I have deliberately added the hyphen, because this
term does NOT mean simply 'tracking branch'. (Grab
your aspirin, and a cold pack for your head, lol.)
Because all branches in git are used for, and only
used for, tracking your project, therefore it could
be said that ALL branches are actually
'tracking-branches', but we don't call them that.
Instead we call them, simply 'branches'.
But then what is a 'tracking-branch'?
TL;DR A 'tracking-branch' is a local name that points to
two branches at the same time.
So when you read 'tracking-branch, it might be
helpful to instead think: 'branch-pair'.
(Normal branches only point to one thing, the
head, which is the commit at a growing tip.
And they do not have any symbolic pointers.)
1) The first branch a 'tracking-branch' points to
is the same as for any other branch: a local head,
(i.e. a young commit in our local repository without
any children.) This is where a tracking-branch
keeps a full local copy of a remote branch.
Note that it doesn't necessiarialy hold a full
duplicate copy of the entire second, remote
repository. If you have cloned the remote
repository then you already have most, if not all
of their commits in your own local repository.
2) The second branch a 'tracking-branch' points to
is a branch on a remote repository.
It does this with a <remote-name>/<branch-name>.
The 'remote-name' is used to find the URL to the
remote repository. See `git remote -v`.
Why point to two branches?
This is to be able to operate on two heads at the
same time, like to copy commits from one head to
the other as `git fetch` and `git push` does.
We have two types of 'tracking-branches' (both on
our local repository):
'local tracking-branches',
with a simple branch name, and
'remote tracking-branches',
with a path-style branch name.
See `git branch -avv`. For example:
这里输出的第一行两行是本地跟踪分支。星号 (*) 前缀 master
告诉我们 master
当前是默认分支(即检出到我们工作区的内容)。顺便说一句,名称 master
是 refs/heads/master
的缩写。
第三行输出是一个简单的本地分支。
第 4 行输出根本不是一个分支,而是指向默认远程跟踪分支的第二个本地 HEAD(除了我们正常的本地 HEAD),或者本示例中的以下分支之一。使用 git remote set-head <remote-name> <remote tracking-branch name>
进行设置。 (请注意,这也与 git remote show <remote-name>
返回的 HEAD 不同,后者是远程存储库 HEAD 的下载值。)
最后两行输出是远程跟踪分支。
请注意,所有分支都引用一个提交 ID(十六进制数)。 remotes/origin/HEAD
不是一个分支,所以它没有这个。
另请注意,前两行和后两行也有对远程分支(在本例中为名为 origin
的远程)的符号引用。
这里的“master”是我们本地的工作分支。而 remotes/origin/master
是名为 master
的分支的本地副本,从我们称为 git fetch
的远程获取(通过 git clone
、git pull
或 origin
) .
(顺便说一句,origin
是我们最初使用 git clone
命令克隆的远程存储库的默认名称。)
So our 'remote tracking-branches' are not remote
branches, on a remote repository, but rather are
local branches, which have a local head of their
own, pointing to a local commit, and also at the
same time symbolically pointing, to a remote
branch.
With `git branch -avv`, notice how two branches can
point to origin/remote:
* the first being the 'local-tracking-branch'
with the name 'master', and with the
'[origin/master]' extra clause, and
* the second being the 'remote-tracking-branch'
with the name 'origin/master'.
NOTE: Though they point to the same remote branch,
the local commit head is not always the same!
Thus they are actually two different branches.
The 'local-tracking-branch' is our working branch,
and the 'remote-tracking-branch' is a copy of the
remote's branch that we cloned from or fetched to
update.
遥控器
git remote # List names of known Remotes
git remote -v # List names of known Remotes and
# show the 2 URL's pointing to them
#
# See '[remote "<names>"]' in
# $ cat .git/config
远程分支(位于远程仓库)
git remote show <remote-name> # Download and view
# a specific Remote's info.
# for example, let's download the information for
# two remotes named origin and upstream:
前导星号 (*) 是一个项目符号,用于标记来自给定遥控器的数据的开始。我们请求从两个遥控器下载,所以我们有两个子弹。
第一行输出给出了远程的名称,以“远程”这个词开头。
2nd 和 3rd 行报告我们本地配置的 获取和推送 URL,用于名为 origin
的远程。也可以使用 git remote -v
查看它们。
第 4 行 报告来自远程存储库的HEAD。你不能设置这个 HEAD。它也不与本地 HEAD 相同,也不与来自 git branch -avv
从第 6 行 开始的是远程存储库拥有的分支列表。
远程分支: 主跟踪 跟踪更新
然后 torek 说 this 剩下的几行:
git remote show 所做的就是通过网络电话使用 git ls-remote
调用 [the remote],并将它们的引用与您的引用进行比较,以猜测 git fetch
和 git push
会做,基于这些结果。 (如果您使用 git pull
,则表示运行 git fetch
,然后运行 git merge
。git remote show
命令也尝试猜测它会做什么。)
本地分支(位于本地存储库中)
git branch -avv # Show ALL 'local branches', verbosely; (3 types):
git branch -rv # -- type 1 -------------------------------------
# Show ONLY 'local branches' that point to
# 'remote branches' (-r = remote; -v = verbose)
#
# This lists your 'Remote tracking branches'!
# From: $ tree .git/refs/remotes/*
#
# They allow us to move snapshots between
# repositories, and to keep a copy of
# Remote's branches locally.
git branch -vv # -- types 2 and 3 ------------------------------
# Show ONLY 'local branches', that point to local
# things, but his includes two different types of
# branches mixed together, for example:
* master de430b6 [origin/master] <comment describing this branch>
updates 3c40299 [origin/updates] <comment describing this branch>
foo de430b6 <comment describing this branch>
请注意,前两个名为 master
和 updates
(上图)的分支在提交编号后都有一个附加字段。例如,对于名为“master”的分支,此字段为 [origin/master]
。
这告诉我们这两个分支不是普通的本地分支,而是本地跟踪分支。与上面的“远程跟踪分支”类似,它们也象征性地指向远程分支。因此,在这种情况下,master
不仅指向本地存储库中的分支 head,而且还指向远程存储库中的 origin/master
。
这些额外的字段由 .git/config 中的参数设置。
相比之下,这里的 foo
是一个简单的普通分支,即非跟踪。
cat .git/config # '[branch "<names>"]' are local
# tracking branches
ls -F .git/refs/heads/* # 'Local' branch names & heads:
# both tracking and non-tracking
ls .git/refs/remotes/<remote-name>/* # 'Remote' tracking branch names & heads
使用 git branch,
git checkout -b
创建,或
通过使用 git clone
克隆远程存储库,或
通过直接编辑 .git/config
或使用这些来明确管理:
遥控器
通过克隆 git 存储库隐式地创建 git remote
git clone
。
git remote add
- 显式添加新的远程名称(到 .git/config)git remote rename
git remote remove
- 删除远程git remote prune
- 删除已在远程上删除的任何本地远程跟踪分支设置属性:
git set-url
- 设置一个 url,或者为远程替换一个 url
git set-url --add
- 将一个 url 附加到远程的 url 列表中
git set-url --delete
- 删除所有匹配某个模式的网址
git set-branches
- 更改跟踪分支的集合
git set-branches --add
- 追加,而不是完全替换当前跟踪的分支列表
git set-head
- 设置 default 远程分支(即远程的 HEAD)
git set-head --auto
- 查询远程以设置远程分支的本地 HEAD
git set-head --delete
- 删除 default 远程分支(即远程的 HEAD)
分支机构
git branch [--set-upstream | --track | --no-track] [-l] [-f] <NewBranchName> [<start-point>] # create branch (start point defaults to HEAD)
git branch (--set-upstream-to=<upstream-branch> | -u <upstream-branch>) [<BranchName>] # link to upstream branch
git branch --unset-upstream [<BranchName>] # unlink to upstream branch
git branch --edit-description [<BranchName>] # edit branch description
git branch (-m | -- move | -M) [<oldBranchName>] <newBranchName> # rename (move) branch; -M = force
git branch (-d | -D) [-r] <BranchName>... # delete branch
使用默认配置,当您 git clone
时,这会自动设置您的遥控器和跟踪分支。但请注意,有些配置设置会禁用或更改其工作方式。
提示使用 --dry-run
和 git fetch
上的 git push
选项,在您执行之前查看会发生什么。< /p>
使用 git fetch
(可能通过调用 git pull
)更新远程提交的本地副本,使您保持最新状态。
如果您不包含 a,则使用默认值。您可以在 .git/config
下的 fetch=
属性中查看 [remote "<remote-name>"]
中的默认值。这可能看起来像这样:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
语法是 [+]?<source>:<destination>
。这意味着从 .git/refs/heads/*
获取引用(通常是提交和标签),它们是远程存储库中的普通简单分支,并将它们放入我们的本地 .git/refs/remotes/origin/*
分支,这些分支是我们的跟踪分支.酷,嗯!顺便说一句,“+”表示更新,即使这不会是快进。
使用 git push <remote> <branch>
将本地提交发送到您有权写入的远程存储库。
我希望这一切都是正确的。