Git分支:主分支vs. origin / master vs. remotes / origin / master

232
我认为我已经在理解git的基本概念方面走上了正确的轨道。
我已经设置并克隆了一个远程仓库。我还创建了一个空的服务器端仓库,并将我的本地仓库与其链接起来。
我的问题是我不明白以下两者之间的区别:
- origin/master vs. remotes/origin/master 据我所知,master 是本地分支,而 remotes/origin/master 是一个远程分支。
但是,origin/master 究竟是什么?

1
@ChristopherWallace:你的编辑在 Meta 上引发了两个问题:“我们真的需要一个[origin]标签吗?”和“什么是真正的[Master]?”。 - Deduplicator
@Deduplicator 这是个问题吗? - nbro
@ChristopherWallace:嗯,许多人似乎认为你创建的标签和你刚刚添加的标签都不好。我也同意这一点,但也许你有什么要补充的讨论内容是之前没有考虑到的。如果没有,那就是这样了。 - Deduplicator
1
可能是 在Git中,origin/master和origin master有什么区别? 的重复。 - roottraveller
跟进问题:为什么.git/refs/origin/master会偏离.git/refs/remotes/origin/master?我现在遇到了这个问题,感到很困扰。 - Paul
7个回答

238

克隆一个远程仓库并运行git branch -a(显示Git知道的所有分支)。 它可能看起来像这样:

* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

这里的master是本地仓库中的一个分支。remotes/origin/master是名为origin的远程仓库上的一个名为master的分支。你可以用origin/master来引用它,例如:

git diff origin/master..master

你也可以将其称为remotes/origin/master

git diff remotes/origin/master..master

这只是指称同一个东西的两种不同方式(顺便说一下,这两个命令的意思都是“显示远程master分支和我的master分支之间的差异)。

remotes/origin/HEAD 是名为 origin 的远程库的默认分支。这使你可以简单地使用 origin 代替 origin/master


6
好的回答。我认为 git branch -a 显示远程分支为 remotes/origin/master 部分是因为底层引用存储在 .git/refs/remotes/origin 中(如果没有被打包)。我认为,git branch -a 命令的输出可以更加清晰,也许可以通过使用其他符号而不是斜杠来区分远程名称和分支名称。 - Matt
18
请注意,git branch -r 仅显示远程分支,将显示分支为 origin/master,因为 remotes/ 前缀不是必需的。 - Matt
3
@misterbiscuit: 真的。输出结果比澄清更加令人困惑。非常感谢,这个对我的问题给出了正确的线索,是一个很棒的答案。 - John Rumpel
1
然而,我对这个答案有点困惑。如果有人更改了远程主分支并且我们还没有获取它,那么remotes/origin/master不就与origin/master不同吗? - iRestMyCaseYourHonor
1
尊敬的法官,如果您还没有进行获取或拉取操作,那么您的本地仓库将不会知道来自远程的任何新提交。remotes/origin/masterorigin/master都指向同一个东西:在名为origin的远程仓库中master分支的最后已知位置(即截至您的仓库上次与远程仓库通信时的位置)。 - Shi
显示剩余2条评论

115

对于像我这样的蒟蒻的简短回答(摘自Torek):

  • origin/master 是“上一次检查时master所在的位置”
  • master 是“基于我所做的事情,master目前所在的位置”

11
原始/主控 = 远程机器的备份,在您上次检查时更新 主控 = 您的原始/主控副本 - sakurashinken

43

其实在您的Git repo中并没有任何“远程”内容1,只有本地名称应该对应另一个不同的repo上的名称。 命名为origin/whatever的内容最初将与您从其克隆的repo上的内容相匹配:

git clone ssh://some.where.out.there/some/path/to/repo # or git://some.where...

复制其他repo并在此过程中记录所有分支及其所指向的提交,然后将它们命名为 refs/remotes/origin/ 并存储在本地repo中。

取决于你之前多久执行 git fetch 或等效操作来更新“外部某处的内容”,他们可能会更改他们的分支,创建新的分支并删除一些。当你执行 git fetch(或真正的 git pull,即fetch加merge)时,你的repo将复制他们的新工作并根据需要更改所有的refs/remotes/origin/<name>条目。 此刻的fetch会使一切匹配(好吧,初始克隆,以及某些情况的 push 也是如此 - 基本上每当Git有机会检查时 - 但请参阅下面的警告)。

Git通常让你用自己的refs/heads/<name>简称,远程的则用origin/<name>,因为很明显哪个是哪个。有时会出现自己创建的分支名称不明显的情况,但在这种情况发生之前不必担心。 :-)只需使用最短的名称,以便显而易见,Git将从那里开始:origin/master 是“上次我检查时master在那里”,master 是“根据我所做的,master在这里”。运行git fetch 来更新Git中“master在那边”的信息。


警告:在Git版本1.8.4之前的某些模式下,git fetch不会更新“上次检查时的master在哪里”(更准确地说,不会更新任何远程跟踪分支)。运行git fetch origingit fetch --all,甚至只是git fetch,会更新。运行git fetch origin master 不会。不幸的是,普通的git pull触发了这个“不会更新”的模式。(这主要只是一个小问题,在Git 1.8.4及更高版本中已修复。)


1嗯,有一件事被称为“remote”。但也是本地的!Git称之为“remote”的是名为origin的东西。它基本上只是在克隆时使用的URL的简称。这也是 origin/master 的来源。名称origin/master被称为远程跟踪分支,有时会缩短为“远程分支”,特别是在较老或更非正式的文档中。


3
非常好的描述,对像我一样的新手来说非常感谢!这说明了为什么她将 origin/master 标签放在 local 仓库图上而不是在 remote 上(我由衷地推荐 Jessica Kerr 的 "Git Happens" 演示文稿,适合初学者学习 git:https://vimeo.com/46010208。在30:00 - 30:19之间我还在犯傻呢)。 - elder elder

13

我会尝试将 @ErichBSchulz 的回答简化,以便初学者理解:

  • origin/master 是远程仓库上主分支的状态。
  • master 是本地仓库上主分支的状态。

1
不错的尝试,但在我看来,如果没有“最后一次我检查过”的话,它会失去重要的观点。 - Alex Martian

9
  1. origin - 这是指向远程仓库的自定义名称,也是最常用的名称。

$ git remote add origin https://github.com/git/git.git --- 你需要运行这个命令来将你的github项目与origin关联。这里的origin是用户定义的。 你可以通过$ git remote rename old-name new-name来重命名它。


  1. master - Git中默认的分支名称为master,无论是在远程还是本地电脑上。

  1. origin/master - 这只是一个指针,用于引用远程仓库中的主分支。记住我说过origin指向远程仓库。

$ git fetch origin - 将对象和引用从远程仓库下载到本地计算机[origin/master]。这意味着它不会影响您的本地主分支,除非您使用$ git merge origin/master将它们合并。记得在运行此命令之前,要切换到正确的分支进行合并。

注意:获取的内容表示为远程分支。获取操作让您有机会在将更改集成到项目副本之前查看更改内容。要显示您的代码与远程仓库之间的差异,请使用$git diff master..origin/master


5

需要澄清一点(也是让我困惑的一点):

“remotes/origin/HEAD 是默认分支”并不完全正确。

在远程仓库中,remotes/origin/master 才是默认分支(上次您检查时)。 HEAD 不是一个分支,它只是指向一个分支。

把 HEAD 理解为您的工作区。当您这样考虑时,“git checkout branchname” 就有了意义,可以将您的工作区文件更改为特定分支的文件。您可以将分支文件“checkout”到您的工作区。从实际目的来看,HEAD 就是您工作区中可见的内容。


更准确地说,HEAD是一个“分支指针”(实际文件在本地repo中通常包含字符串ref:refs/heads/master,除非它是“分离的”,这是另一回事)。然而,在clone解释“远程HEAD”的方式上存在某种错误:传输协议根本无法发送间接分支,只能发送原始SHA-1,因此git有一个替代方法使其“基本工作”。但偶尔会有人遇到奇怪的情况。当出错时,我有点希望git根本不要创建remotes/origin/HEAD - torek

4

我认为这个 git 斜杠符号最好通过查看你的 .git 文件夹内部来理解。


例如,这是我的 LibreOffice 源代码库的 .git 树结构(有所缩减)。

Linux中,sudo apt-get install tree 命令可以用来查看它。
Windows中,我认为 tree 命令仍然有效。

向下滚动并查看底部附近的引用(也称为“参考”):

$ tree  
.  
├── branches  
├── config  
├── description  
├── FETCH_HEAD  
├── gitk.cache  
├── HEAD  
├── hooks  
│   ├── applypatch-msg.sample  
    ...
├── index  
├── info  
│   └── exclude  
├── logs  
│   ├── HEAD  
│   └── refs  
│       ├── heads  
│       │   ├── master  
│       │   └── remotes  
│       │       └── origin  
│       └── remotes  
│           └── origin  
│               ├── distro  
│               │   ├── cib  
│               │   │   └── libreoffice-6-0  
│               │   ├── collabora  
│               │   │   └── cp-6.0  
│               │   └── lhm  
│               │       └── libreoffice-5-2+backports  
│               ├── HEAD  
│               ├── libreoffice-6-2  
│               ├── master  
│               └── private  
│                   └── mst  
│                       └── sw_redlinehide_4a  
├── objects  
│   ├── info  
│   └── pack  
│       ├── pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.idx  
│       ├── pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.pack  
│       ├── pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.idx  
│       └── pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.pack  
├── ORIG_HEAD  
├── packed-refs  
└── refs  
    ├── heads  
    │   ├── master  
    │   └── remotes  
    │       └── origin  
    ├── remotes  
    │   └── origin  
    │       ├── distro  
    │       │   ├── cib  
    │       │   │   └── libreoffice-6-0  
    │       │   ├── collabora  
    │       │   │   └── cp-6.0  
    │       │   └── lhm  
    │       │       └── libreoffice-5-2+backports  
    │       ├── HEAD  
    │       ├── libreoffice-6-2  
    │       ├── master  
    │       └── private  
    │           └── mst  
    │               └── sw_redlinehide_4a  
    └── tags  
        └── libreoffice-6-2-branch-point  

32 directories, 45 files

如果内容排版如下所示,可能会更加清晰易懂,但实际上并非如此:

repositories (i.e. independent trees)
├──local
│  └──master
│
└──origin1
│  └──master
└──origin2
   └──master

我们有三种基本类型的引用: headsremotestags
  • .git/refs/heads 存储我们的本地 master
  • .git/refs/remotes 可以存储多个远程,尽管目前我们只有一个名为 origin 的远程。
  • .git/refs/tags(在其他地方讨论)。
因此,origin 是我们唯一的远程。它拥有 origin/master
我们发现我们有2个HEADS(指向当前分支的指针),一个是本地的,一个是远程的。
$ cat .git/HEAD                        #         local:  HEAD -> master
ref: refs/heads/master

$ cat .git/refs/remotes/origin/HEAD    # remote origin:  HEAD -> master
ref: refs/remotes/origin/master

如果你列出你的分支

$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/aoo/aw080
  remotes/origin/aoo/trunk
  remotes/origin/distro/capgemini/cg-4.1
  remotes/origin/distro/cib/libreoffice-5-0
  remotes/origin/distro/cib/libreoffice-5-1
  remotes/origin/distro/cib/libreoffice-5-2
  ...
  • 列出的第一个分支(master)是唯一一个不是远程分支的。因此,在这种情况下,我们只有一个本地分支。这是我们为自己的新分支和随后的提交开始工作的地方。

接下来,你可能有许多远程跟踪分支,在这里我们确实有许多。你可以通过前缀 'remotes/' 来识别它们是远程跟踪分支。在这里显示的是名为 origin 的远程库的内容。

  • 所以第二行是 origin 的 当前分支 指针。Remotes/origin: HEAD --指向--> master。这表明在远程仓库中,当前分支是他们命名为 master 的分支(不要与我们本地命名为 master 的分支混淆)。

  • 其余的分支没有在 .git/refs/ 树中找到,而是在 .git/packed-refs 中找到。

当我们 git fetch 时,我们会将更改从远程仓库下载到我们的远程跟踪仓库。

当我们 git merge 时,我们将合并此本地远程跟踪仓库中的更改到我们的工作本地分支或分支,此处是合并到我们的 master 分支。

(当我们 git pull 时,我们将这两个步骤结合到一起进行。)


还有一个有趣的事情要注意,即 master 的本地和远程 UUID 目前指向同一节点(也称为“提交”):

$ cat refs/heads/master                   # local         master
1ca409292272632f443733450313de5a82c54a9c

$ cat refs/remotes/origin/master          # remote origin master
1ca409292272632f443733450313de5a82c54a9c

所以我们本地的主分支指向与远程的原始主分支相同的位置:
[local] master = [remote] origin master

最后,我认为查看.git/packed-refs也是有用的。

$ cat packed-refs 
# pack-refs with: peeled fully-peeled 
3c1d4742e649fe9c8aed8c2817fe3e1f3364f298 refs/remotes/origin/aoo/aw080
e87c8b7922e9a73e0abb7f9a7a47c9ac3374a826 refs/remotes/origin/aoo/trunk
b70fdffb041c12f124dcc0822b61bf3450e53137 refs/remotes/origin/distro/capgemini/cg-4.1
5dbc3f1754809b9489faaf380b1a4bdbcfbb6205 refs/remotes/origin/distro/cib/libreoffice-5-0
cfdbc96ca47d68d6785fd21829a8d61f49d6e591 refs/remotes/origin/distro/cib/libreoffice-5-1
5189c8c47461ef09739086e55512fc6a10245273 refs/remotes/origin/distro/cib/libreoffice-5-2
3bee5917569ca8e6ee3b086458f5b1a917b88ca1 refs/remotes/origin/distro/cib/libreoffice-5-3
92fbe703f9ca480d3a2b8610d87e991c729edf77 refs/remotes/origin/distro/cib/libreoffice-5-4
05c0a5df66cc69d75280f05b804cf82f3387d42b refs/remotes/origin/distro/cib/libreoffice-6-0
7fe193e759b24b90852e6e327115b77114d7b119 refs/remotes/origin/distro/cib/libreoffice-6-1
8187f7aa413e7ef7b377eea2b057d336bf256867 refs/remotes/origin/distro/collabora/cd-5.3
7a6b608591e21ef61dc05cff9fc58da531035755 refs/remotes/origin/distro/collabora/cd-5.3-3.1
....

毫无疑问,这留下了更多的问题而不是答案,但我认为它可以开始帮助您回答自己关于什么是什么的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接