本地分支,本地跟踪分支,远程分支和远程跟踪分支之间有什么区别?

ede*_*ded 139 git version-control git-remote git-branch

我刚刚开始使用Git,我在不同的分支之间真的很困惑.任何人都可以帮我弄清楚以下分支类型是什么?

  • 当地分公司
  • 本地跟踪分支
  • 远程分支
  • 远程跟踪分支

他们之间有什么区别?他们如何相互合作?

我想,快速演示代码将非常有用.

Fli*_*imm 173

这是一个很长的答案.

遥控器:

如果您正在协作使用Git,则可能需要将提交与其他计算机或位置同步.每个机器或位置在Git的术语中称为远程,并且每个机器或位置可以具有一个或多个分支.大多数情况下,你只会有一个名字origin.要列出所有遥控器,请运行git remote:

$ git remote
bitbucket
origin
Run Code Online (Sandbox Code Playgroud)

您可以通过运行以下命令查看这些远程名称的快捷方式位置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)
Run Code Online (Sandbox Code Playgroud)

每个远程都有一个目录位于git/refs/remotes/:

$ ls -F .git/refs/remotes/
bitbucket/ origin/
Run Code Online (Sandbox Code Playgroud)

您机器上的分支机构:

TLDR:在您的本地计算机上,您有三种类型的分支:本地非跟踪分支,本地跟踪分支和远程跟踪分支.在远程计算机上,您只有一种类型的分支.

1.地方分支机构

您可以通过运行git branch以下命令查看计算机上所有本地分支的列表:

$ git branch
master
new-feature
Run Code Online (Sandbox Code Playgroud)

每个本地分支都有一个文件.git/refs/heads/:

$ ls -F .git/refs/heads/
master new-feature
Run Code Online (Sandbox Code Playgroud)

您的计算机上有两种类型的本地分支:非跟踪本地分支和跟踪本地分支.

1.1非跟踪本地分支机构

非跟踪本地分支不与任何其他分支相关联.您可以通过运行创建一个git branch <branchname>.

1.2.跟踪当地分支机构

跟踪本地分支与另一个分支相关联,通常是远程跟踪分支.您可以通过运行创建一个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
Run Code Online (Sandbox Code Playgroud)

从此命令的输出中,您可以看到本地分支master正在跟踪远程跟踪分支origin/master,而本地分支new-feature不跟踪任何内容.

查看哪些分支跟踪分支的另一种方法是查看.git/config.

跟踪本地分支是有用的.他们允许您运行git pullgit 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>
Run Code Online (Sandbox Code Playgroud)

2.远程跟踪分支机构(仍在您的机器上)

您可以通过运行git branch -r以下命令查看计算机上所有远程跟踪分支的列表:

$ git branch -r
bitbucket/master
origin/master
origin/new-branch
Run Code Online (Sandbox Code Playgroud)

每个远程跟踪分支都有一个文件.git/refs/<remote>/:

$ tree -F .git/refs/remotes/
.git/refs/remotes/
??? bitbucket/
?   ??? master
??? origin/
    ??? master
    ??? new-branch
Run Code Online (Sandbox Code Playgroud)

将远程跟踪分支视为远程计算机包含的本地缓存.您可以使用更新的远程跟踪分支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)
Run Code Online (Sandbox Code Playgroud)

git remote命令通过网络查询远程计算机的分支.它不会更新本地计算机上的远程跟踪分支,使用git fetchgit pull为此.

从输出中,您可以通过查看标题"远程分支"(忽略标记为"陈旧"的行)查看远程计算机上存在的所有分支.

如果您可以登录到远程计算机并在文件系统中找到存储库,则可以查看其下的所有分支refs/heads/.

备忘单:


您可能已经注意到在某些命令中,您使用了<remote>/<branch>其他命令<remote> <branch>.示例:git branch origin/hello-kittygit push --delete origin hello-kitty.

它看似随意,但有一种简单的方法可以记住何时使用斜杠以及何时使用空格.当你使用斜杠时,你指的是你自己机器上的远程跟踪分支,而当你使用空间时,你实际上是通过网络处理远程机器上的分支.

  • 我喜欢最后一点关于空格和斜杠之间的区别! (3认同)

SNc*_*Nce 105

一个地方分支的一个分支,只有你(本地用户)可以看到.它仅存在于您的本地计算机上.

git branch myNewBranch        # Create local branch named "myNewBranch"
Run Code Online (Sandbox Code Playgroud)

远程分支是上远程位置处的分支(在大多数情况下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"
Run Code Online (Sandbox Code Playgroud)

一个远程跟踪分支是远程分支的本地副本.当myNewBranch推到origin使用上面的命令,命名为远程跟踪分支origin/myNewBranch是你的机器上创建的.这种远程跟踪分支追踪远程分支myNewBranchorigin.您可以使用或更新远程跟踪分支以与远程分支同步.git fetchgit 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"
Run Code Online (Sandbox Code Playgroud)

一个地方跟踪分支本地分支,其跟踪的另一个分支.这样您就可以向/从另一个分支推送/拉出提交.在大多数情况下,本地跟踪分支跟踪远程跟踪分支.当您将本地分支推送到origin使用git push command带有-u选项时(如上所示),您可以设置本地分支myNewBranch以跟踪远程跟踪分支origin/myNewBranch.这需要使用git pushgit 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.
Run Code Online (Sandbox Code Playgroud)

  • @mskw否,本地跟踪分支和本地(非跟踪)分支的关联不同.本地分支不与任何分支相关联.它只是一个独立存在于本地计算机上的分支.本地跟踪分支与远程跟踪分支相关联.因此,您可以相互推送/拉出提交. (2认同)

Eri*_*son 12

当地分行:

机器上的一个分支,您可以在其中工作并添加提交.您可以列出这些分支git branch.

本地分支(跟踪):

配置为对应于远程分支的普通本地分支.这有利于git pullgit push不必指定存储库和分支名称的能力.git status当您的分支位于遥控器的前方或后方时,跟踪还会通知您.

远程分支:

只是远程存储库上的分支 - 通常在诸如GitHub等服务器上.

远程跟踪分支:

远程分支的本地副本.永远不应该编辑该分支.其目的是跟踪远程分支的当前状态.可以查看远程跟踪分支git branch -r,通常看起来像origin/master(repo name后跟斜杠后跟分支名称).运行git fetch将更新远程跟踪分支以反映相应远程分支的状态.

git branch -avv是我个人最喜欢的,它可以快速浏览我的机器上哪些分支机构,远程机器上的哪些分支机构以及每台分支机构的最新提交.该-a部分指定应显示所有分支(远程和本地).最后的v's表示详细(它显示了最后一次提交哈希和消息).感谢@Flimm指出第二个v添加有关哪个本地分支正在跟踪哪个远程的信息.


Ell*_*iew 8

概述

TL;DR - 这是经过组织的,因此您可以跳到您需要了解的内容。

以下是我将要介绍的内容:

  • 快速概述 - 4 种类型的分支是什么以及在哪里可以找到它们
  • 简短词汇表 - 与分支机构相关的基本原则和术语
  • 调查 - 如何检查本地和远程分支机构
  • 相关文件 - 配置文件
  • 配置 - 如何查看和设置您的分支配置
  • 协作 - 如何使用远程分支

快速概览

本地分支是我们本地存储库上的一个名称,指是此处的head 。

远程分支是远程存储库上的一个名称,指是那里的头。


简单分支是引用一件事的本地名称:

  1. 它直接指向本地头(即特定的提交;不断增长的提示)

跟踪分支是一个本地名称,引用了两件事:

  1. 它直接指向本地头(即特定的提交;不断增长的提示),并且
  2. 它象征性地指向远程存储库上的第二个分支。

有两种跟踪分支:

  • local - 分支指向本地头。
    这些称为本地跟踪分支(下面有更多相关内容。)

  • 远程- 分支指向远程头的本地副本。
    这些称为远程跟踪分支(下面有更多相关内容。)


以下是 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
--------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

简短词汇表

术语“远程”“分支”似乎含义过多。

短语“ trackingbranch”尤其令人困惑,因为它与“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.
Run Code Online (Sandbox Code Playgroud)
'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  
Run Code Online (Sandbox Code Playgroud)
'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 its 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.
                   
Run Code Online (Sandbox Code Playgroud)
'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.
Run Code Online (Sandbox Code Playgroud)
'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'?
Run Code Online (Sandbox Code Playgroud)
         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`.
Run Code Online (Sandbox Code Playgroud)
                    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:
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 这里输出的第一两行是本地跟踪分支。星号 (*) 前缀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”是我们本地的工作分支。And是从我们调用的远程获取(通过或)remotes/origin/master的名为 的分支的本地副本。mastergit fetchgit clonegit pullorigin

(顺便说一句,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.
Run Code Online (Sandbox Code Playgroud)

调查

遥控器

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
Run Code Online (Sandbox Code Playgroud)

远程分支(位于远程存储库)

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:
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 前导星号(*)是一个项目符号,用于标记给定远程数据的开始。我们请求从两个遥控器下载,所以我们有两个项目符号。

  • 第一输出给出了远程的名称,以“remote”一词开头。

  • 2 行和第 3行报告我们本地配置的名为 的远程的获取和推送 URLorigin。还可以使用 来查看它们git remote -v

  • 4行报告来自远程存储库的 HEAD。你不能设置这个 HEAD。它也不与本地 HEAD 相同,也不与来自远程的本地读取相同。git branch -avv

  • 从第 6行开始是远程存储库拥有的分支列表

    远程分支:主跟踪更新跟踪

  • 然后托雷克说对剩下的几行说了这样的话:

git Remote show 所做的就是git ls-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>
Run Code Online (Sandbox Code Playgroud)

请注意,前两个分支名为master请注意,名为和updates(见上图)在其提交编号后都有一个附加字段。例如,对于名为“master”的分支,此字段为[origin/master]

这告诉我们这两个分支不是普通的本地分支,而是本地跟踪分支。与上面的“远程跟踪分支”类似,它们也象征性地指向远程分支。因此master,在这种情况下, 不仅指向本地存储库中的分支,而且还指向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
Run Code Online (Sandbox Code Playgroud)

配置

使用 创建git branch, git checkout -b,或者使用 克隆远程存储库git clone,或者通过直接编辑来显式管理.git/config或使用这些来显式管理:


遥控器

通过使用 .git 克隆 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- 删除所有与某个模式匹配的 url

  • git set-branches- 更改跟踪分支的集合

  • git set-branches --add- 追加而不是完全替换当前跟踪的分支列表

  • git set-head- 设置默认远程分支(即远程的 HEAD)

  • git set-head --auto- 查询远程以设置远程分支的本地 HEAD

  • git set-head --delete- 删除默认的远程分支(即远程的 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
Run Code Online (Sandbox Code Playgroud)

合作

使用默认配置,当您git clone自动设置遥控器和跟踪分支时。但请注意,有些配置设置将禁用或更改其工作方式。


提示在执行此操作之前,请使用和--dry-run选项来查看会发生什么。git fetchgit push


使用git fetch(可能通过调用git pull)更新远程提交的本地副本以使您保持最新状态。

如果不包含 a,则使用默认值。.git/config您可以在fetch=下的属性中查看默认值[remote "<remote-name>"]。这可能看起来像这样:

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
Run Code Online (Sandbox Code Playgroud)

语法是[+]?<source>:<destination>. 这意味着获取.git/refs/heads/*远程存储库中正常、简单分支的引用(通常是提交和标签),并将它们放入我们的本地.git/refs/remotes/origin/*分支,即我们的跟踪分支。酷,嗯!顺便说一句,“+”表示更新,即使这不会快进。


用于git push <remote> <branch>将本地提交发送到您有权写入的远程存储库。


我希望这一切都是正确的。