我已经设置并克隆了一个远程仓库。我还创建了一个空的服务器端仓库,并将我的本地仓库与其链接起来。
我的问题是我不明白以下两者之间的区别:
- origin/master vs. remotes/origin/master 据我所知,master 是本地分支,而 remotes/origin/master 是一个远程分支。
但是,origin/master 究竟是什么?
克隆一个远程仓库并运行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
。
git branch -a
显示远程分支为 remotes/origin/master
部分是因为底层引用存储在 .git/refs/remotes/origin
中(如果没有被打包)。我认为,git branch -a
命令的输出可以更加清晰,也许可以通过使用其他符号而不是斜杠来区分远程名称和分支名称。 - Mattgit branch -r
仅显示远程分支,将显示分支为 origin/master
,因为 remotes/
前缀不是必需的。 - Mattremotes/origin/master
和origin/master
都指向同一个东西:在名为origin
的远程仓库中master
分支的最后已知位置(即截至您的仓库上次与远程仓库通信时的位置)。 - Shi对于像我这样的蒟蒻的简短回答(摘自Torek):
其实在您的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 origin
或git fetch --all
,甚至只是git fetch
,会更新。运行git fetch origin master
不会。不幸的是,普通的git pull
触发了这个“不会更新”的模式。(这主要只是一个小问题,在Git 1.8.4及更高版本中已修复。)
1嗯,有一件事被称为“remote”。但也是本地的!Git称之为“remote”的是名为origin
的东西。它基本上只是在克隆时使用的URL的简称。这也是 origin/master
的来源。名称origin/master
被称为远程跟踪分支,有时会缩短为“远程分支”,特别是在较老或更非正式的文档中。
origin/master
标签放在 local
仓库图上而不是在 remote
上(我由衷地推荐 Jessica Kerr 的 "Git Happens" 演示文稿,适合初学者学习 git:https://vimeo.com/46010208。在30:00 - 30:19之间我还在犯傻呢)。 - elder elder我会尝试将 @ErichBSchulz 的回答简化,以便初学者理解:
$ git remote add origin https://github.com/git/git.git
--- 你需要运行这个命令来将你的github项目与origin关联。这里的origin是用户定义的。
你可以通过$ git remote rename old-name new-name
来重命名它。
$ git fetch origin
- 将对象和引用从远程仓库下载到本地计算机[origin/master]。这意味着它不会影响您的本地主分支,除非您使用$ git merge origin/master
将它们合并。记得在运行此命令之前,要切换到正确的分支进行合并。
注意:获取的内容表示为远程分支。获取操作让您有机会在将更改集成到项目副本之前查看更改内容。要显示您的代码与远程仓库之间的差异,请使用$git diff master..origin/master
需要澄清一点(也是让我困惑的一点):
“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我认为这个 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
$ 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
...
接下来,你可能有许多远程跟踪分支,在这里我们确实有许多。你可以通过前缀 '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
....
.git/refs/origin/master
会偏离.git/refs/remotes/origin/master
?我现在遇到了这个问题,感到很困扰。 - Paul