Git 远程仓库
查看【Git】专题可浏览更多内容
在使用版本控制系统时,大部分的操作都在「本地仓库」进行,但当需要与团队协作进行数据共享时,就需要「远程仓库」了。
克隆一个远程仓库
在 Git | 入门 中介绍到,如何获取一个远程仓库,答案是使用克隆,如:
# git clone <url>
git clone https://example.com/git-repo.git
查看远程仓库信息
当克隆一个远程仓库的同时,Git 会自动记录其链接。默认使用「origin」来标识所克隆的原始仓库,「origin」就像是分支中的「master」或「main」,这是一个约定俗成的名称。
然后我们来看一下远程仓库信息:
git remote -v
origin https://example.com/git-repo.git (fetch)
origin https://example.com/git-repo.git (push)
每个远程仓库包含两行:
- fetch:用来进行抓取的 URL;
- push:用来把本地仓库中的数据推送到远程仓库的 URL;
很多情况下这两个 URL 都是相同的,但出于安全或性能等方面的考虑,可以对抓取和推送的设置不同的 URL 地址。
此外可以对一个本地仓库设置很多个远程链接,这是没有数量限制的。
连接本地仓库与远程仓库
如果已经有了一个本地仓库,想要与某个远程仓库连接呢?
# git remote add [<选项>] <名称> <地址>
git remote add backup https://backup.com/git-repo.git
上述命令表示增加一个远程仓库名称为「backup」,地址为「https://backup.com/git-repo.git」
这里的「backup」相当于使用克隆命令后 Git 默认创建的「origin」。
再次使用命令
git remote -v
backup https://backup.com/git-repo.git (fetch)
backup https://backup.com/git-repo.git (push)
origin https://example.com/git-repo.git (fetch)
origin https://example.com/git-repo.git (push)
除了「origin」现在还多了刚才添加的「backup」
如果你当前的仓库是在本地使用
git init
命令创建而不是克隆来的,那么将没有origin
,这是正常的
本地与远程仓库的工作流程
首先要知道本地与远程的数据同步并不是一个实时的流程,那么就需要:
- 在需要的时候使用
git fetch
抓取远程仓库的数据,以了解团队的其他人也没有做什么新的改动; - 如果没有,而你有新的改动要推送上去就可以使用
git push
命令推送上去; - 如果有新的改动,就可以先
git fetch
使远程仓库的数据抓取到远程跟踪分支,然后git merge
到本地仓库的分支上,当然还有一个组合命令git pull
可以同时做到这些;
❓ 等等,什么是「远程跟踪分支」?
远程跟踪分支
当使用命令查看所有分支时:
git branch -a
* master
remotes/origin/master
其中的 remotes/origin/master
就是远程跟踪分支,它是远程分支的本地只读副本,处于本地分支与远程分支之间,也就是说流程应该是这样的:
本地分支 <=> 远程跟踪分支 <=> 远程分支
在使用克隆获取远程仓库时 Git 会自动建立好追踪关系,使用命令:
git branch -vv
* master 834365f [origin/master] Add Title
如上示例就可以看到本地的 master
跟踪远程跟踪分支也就是 origin/master
,也就是说 origin/master
是本地分支 master
的上游分支。
除了 git branch -vv
还可以使用命令查看:
git remote show origin
* 远程 origin
获取地址:git@github.com:Example/Markdown.git
推送地址:git@github.com:Example/Markdown.git
HEAD 分支:master
远程分支:
master 已跟踪
为 'git pull' 配置的本地分支:
local 与远程 remote 合并
master 与远程 master 合并
为 'git push' 配置的本地引用:
master 推送至 master (最新)
如果不是通过克隆而是手动添加的远程仓库,那么在推送时就会遇到这样的错误:
致命错误:当前分支 master 没有对应的上游分支。
为推送当前分支并建立与远程上游的跟踪,使用
git push --set-upstream origin master
为了让没有追踪上游的分支自动配置,参见 'git help config' 中的 push.autoSetupRemote。
这就是本地仓库的当前分支没有设置上游的远程追踪分支,此时可以使用 -u
推送并进行跟踪:
# 也可以 git push --set-upstream origin master
git push -u origin master
枚举对象中: 4, 完成.
对象计数中: 100% (4/4), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (2/2), 完成.
写入对象中: 100% (3/3), 274 字节 | 274.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0
remote:
remote: Create a pull request for 'master' on GitHub by visiting:
remote: https://github.com/Example/Markdown/pull/new/master
remote:
To github.com:Example/Markdown.git
* [new branch] master -> master
分支 'master' 设置为跟踪 'origin/master'。
除了在推送时指定,也可以在创建分支时指定追踪某个远程追踪分支,以名为 remote
的远程跟踪分支为例:
git branch --track local origin/remote
分支 'local' 设置为跟踪 'origin/remote'。
那么如果是将一条已经存在的分支设置追踪某个远程跟踪分支呢?以名为 remote
的远程跟踪分支为例:
git branch --set-upstream-to=origin/remote
跟踪分支主要是为了让我们得知本地分支和远程分支的状态,即:
- 如果本地分支上提交了一些改动,且没有发布它和推送到远程仓库中。相对于这些提交来说的本地分支就「领先 (ahead)」于那些它所对应的远程分支。
- 如果团队的其他开发人员提交并且发布了一些改动到远程仓库中,这时远程仓库就拥有了那些你还没有下载到本地仓库的提交。你的本地仓库就「落后 (behind)」于它所关联的远程仓库。
举个例子,在追踪远程分支后,在本地分支上对一个文件进行改动并提交,此时查看状态:
git status
位于分支 dev
您的分支领先 'origin/dev' 共 1 个提交。
(使用 "git push" 来发布您的本地提交)
无文件要提交,干净的工作区
可以看到提示「您的分支领先 ‘origin/dev’ 共 1 个提交。」
抓取远程仓库数据
在连接到远程仓库后,还需要对远程仓库进行数据更新,因为与远程仓库仅仅是建立了连接关系,还没有进行任何数据交换。
Git 会在你的本地仓库中保存远程数据的信息(例如分支,提交等等)。但是它并不是实时地连接到的远程仓库上的:
git branch -a
* master
remotes/origin/master
如果远程仓库创建了一个新分支如 feature
,这时使用 git branch -a
是看不到的,但可以使用命令:
git ls-remote
From git@github.com:Example/Markdown.git
834365f4351ec5b902a11504c31580cf6e70e458 HEAD
55fd276ceae56769a8d9c9fa57144301a9c5c974 refs/heads/feature
834365f4351ec5b902a11504c31580cf6e70e458 refs/heads/master
这样就能看到远程的分支和提交 ID,然后抓取一下远程仓库的数据:
git fetch origin
再使用 git branch -a
就可以看到了
推送改动至远程仓库
# git push <远程仓库名> <远程仓库上的分支>
git push origin master
如果已经建立了跟踪关系,就可以简写成 git push
。
拉取远程仓库的改动
# git pull <远程仓库名> <远程仓库上的分支>
git pull origin master
git pull
命令将会从远程分支下载所有的新的提交到你的本地副本中来。
它实际上就是「抓取 (fetch)」命令和「合并 (merge)」命令的组合 (下载数据并整合到本地副本)。
和 git push
命令一样,如果你本地的 HEAD 分支还没有创建任何一个「跟踪」链接,你就必须告诉 Git,你要从哪一个远程仓库上的哪一分支中抓取数据(例如 git pull origin master
),如果已经存在了一个链接,就可以简写成 git pull
。
整合的目标并不基于存在什么样的跟踪链接,它总是会被整合到你的本地 HEAD 分支中,也就是你的工作副本。
调和分离的分支
在新版本 Git 中,当出现偏离的分支时会遇到这样的提示:
提示:您有偏离的分支,需要指定如何调和它们。您可以在执行下一次
提示:pull 操作之前执行下面一条命令来抑制本消息:
提示:
提示: git config pull.rebase false # 合并
提示: git config pull.rebase true # 变基
提示: git config pull.ff only # 仅快进
提示:
提示:您可以将 "git config" 替换为 "git config --global" 以便为所有仓库设置
提示:缺省的配置项。您也可以在每次执行 pull 命令时添加 --rebase、--no-rebase,
提示:或者 --ff-only 参数覆盖缺省设置。
这就需要为分支的合并方式作出设置:
# 合并,先尝试 fast-forward,如果快速合并失败则使用正常合并
git config pull.rebase false
# 变基
git config pull.rebase true
# 仅快进 fast-forward
git config pull.ff only
或是每次执行使命时带上选项:
git pull [--rebase | --no-rebase | --ff-only]
删除远程分支
如果一个主题分支的工作已经完成了,需要删除本地分支以及解除与远程分支的关联:
# -d, --delete
git branch -d dev
# -r, --remotes 作用于远程跟踪分支
git branch -dr origin/dev
如果需要删除远程仓库上的分支,例如删除 dev
分支:
# git push <remote> --delete <branch>
git push origin -d dev
⚠️ 注意:对于远程仓库的操作都需要谨慎以免出错。
小结
- 使用
git clone
命令可用于克隆一个远程仓库上的项目; - 使用
git remote
命令可用于管理远程仓库,选项add
用于添加远程仓库、set-url
用于修改远程仓库 URL、rm
用于删除远程仓库设置,git remote show origin
用于显示远程仓库相详细信息 (获取、推送地址、远程分支等); - 使用
git branch -a
查看本地与远程的分支,-v
与-vv
可以查看本地与远程跟踪分支的跟踪关系、提交信息等,除了git branch
命令还可以使用git ls-remote
; - 远程跟踪分支是远程分支在本地的只读副本,克隆时会自动设置跟踪关系,如果本地分支没有跟踪关系可以在推送时使用
git push -u
指定为哪个远程服务器哪条分支,也可在创建本地分支时使用git branch --track
指定,或是指定一条已经存在的本地分支:git branch --set-upstream-to=
; - 本地与远程的数据并不是实时同步,所以在需要时可以使用
git fetch
获取远程仓库的数据; - 需要推送本地数据到远程仓库时使用
git push
命令; - 拉取远程仓库改动到本地仓库时使用
git pull
命令,它是git fetch
获取数据到远程跟踪分支 +git merge
从远程跟踪分支这个本地只读副本合并到本地仓库数据的组合命令;