Git 专题 13 —— remote
git是分布式版本管理工具,它没有中央仓库。但多人协作时,我们依然需要一个集散地,让协作成员之间统一往集散地推送和拉取更新。否则,点对点的沟通,效率会很低。
所以就引出了git中远端仓库的概念。
概念
我们之前所有的操作都是在本地仓库完成的,和本地仓库对应的是远端仓库。那么本地有若干分支,远端仓库是不是也有对应的若干分支呢?
当然。
我们探讨一个问题,在离线状态下,git是不是无从知道远端仓库的任何状态?
我让网络下线,查询从github克隆下来的本地仓库的状态,结果它告诉我本地仓库的master分支是up to date with 'origin/master'
。
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
实际上,git的分支有三种:
- 本地分支,我们可以通过
<branch>
写法访问它。 - 远端分支,我们可以通过
<remote branch>
写法访问它。 - 远端分支引用,我们可以通过
<remote/branch>
写法访问它。实际上它也是本地分支,只不过我们无法操作它,只有git的网络操作才可以更新它。离线状态下,git给的状态就是本地分支和远端分支引用的比较结果。
git官方把我所说的
远端分支引用
称为远端分支
。知道谁是谁就行了,名字不重要🤔我是马蹄疾
我们看一下本地的远端分支引用。
.git/
.git/refs/
.git/refs/remotes/
.git/refs/remotes/origin/
.git/refs/remotes/origin/HEAD
.git/refs/remotes/origin/master
默认的远端仓库名就叫origin
。它也有master分支指针,也有HEAD指针。
拉取
如果远端仓库有新的提交或者新的分支,我们需要运行git fetch
命令来拉取更新。
$ git fetch
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:veedrin/git
3893459..0f80eeb master -> origin/master
这个命令是git fetch origin
的缩写。因为origin
是远端仓库的默认名称,所以可以省略。如果有手动添加的远端仓库,那就必须指定远端仓库的名称了。
这个命令做了什么呢?
它会把新的提交和新的分支拉取到本地,然后更新本地的远端分支引用到最新的提交。
git fetch
仅仅是将远端的更新拉取下来,同步本地的远端分支引用,不会对本地分支有任何影响。我们需要手动执行合并操作才能更新本地分支。
$ git merge origin/master
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
当然,有一个更简单的操作。
$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
Unpacking objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
From github.com:veedrin/git
4fbd1d4..d9785d7 master -> origin/master
Updating 4fbd1d4..d9785d7
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
git pull
就是git fetch
和git merge
的一键操作。
推送
推送到远端的命令是git push <remote-name> <remote-branch-name>
。
$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 261 bytes | 261.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:veedrin/git.git
3eaa1ae..2bd3c9d master -> master
如果当前分支对远端分支设置了追踪的话,也可以省略分支名。
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 261 bytes | 261.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:veedrin/git.git
3eaa1ae..2bd3c9d master -> master
有时候本地分支和远端分支同时有新的提交,直接push
是不行的。
$ git push
To github.com:veedrin/git.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git@github.com:veedrin/git.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
有两种方式解决。
第一是先把远端的更新拉下来,有冲突则解决冲突,没冲突则再推送。
第二是强推。有时候我们就是想覆盖远端对吧,也不是不行,但是必须十分谨慎。而且不要在公共分支上强制推送。
$ git push -f
Counting objects: 24, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (24/24), 3.72 KiB | 1.24 MiB/s, done.
Total 24 (delta 0), reused 3 (delta 0)
To github.com:veedrin/git.git
+ 54d741b...2db10e0 master -> master (forced update)
实际开发时我们会建很多特性分支,推送到远端,通过测试后再合入主分支。使用git push <remote-name> <remote-branch-name>
每次都要指定远端分支名,如果会有多次推送,我们可以在推送时设置本地分支追踪远端分支,这样下次就可以直接推送了。
也可以简写成git push -u <remote-name> <remote-branch-name>
。
$ git push --set-upstream origin dev
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 255 bytes | 255.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'dev' on GitHub by visiting:
remote: https://github.com/veedrin/git/pull/new/dev
remote:
To github.com:veedrin/git.git
* [new branch] dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
然后我们在.git/config
文件中能看到多了一条配置。
[branch "dev"]
remote = origin
merge = refs/heads/dev
查看
查看远端仓库的命令是git remote
。
$ git remote
origin
加-v
参数可以查看更为详细的信息,-v
是--verbose
的缩写。
$ git remote -v
origin git@github.com:veedrin/git.git (fetch)
origin git@github.com:veedrin/git.git (push)
查看某个远端仓库的信息,可以使用命令git remote show <remote-name>
。
$ git remote show origin
* remote origin
Fetch URL: git@github.com:veedrin/git-1.git
Push URL: git@github.com:veedrin/git-1.git
HEAD branch: master
Remote branches:
dev tracked
master tracked
Local branches configured for 'git pull':
dev merges with remote dev
master merges with remote master
Local refs configured for 'git push':
master pushes to master (up to date)
添加
添加新的远端仓库,使用git remote add <shortname> <url>
命令。
$ git remote add horseshoe https://github.com/veedrin/horseshoe
然后本地就多了一个远端仓库。
$ git remote
horseshoe
origin
除了添加远端仓库,我们还可以添加本地分支对远端分支的追踪。
$ git checkout -b dev origin/dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Switched to a new branch 'dev'
创建dev分支的同时,也设置了对远端分支dev的追踪,这样下次推送的时候就不需要指定了。
当然,远端分支引用必须得存在才行。
$ git checkout -b dev origin/dev
fatal: 'origin/dev' is not a commit and a branch 'dev' cannot be created from it
git也提供了快捷方式。
$ git checkout --track origin/dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Switched to a new branch 'dev'
重命名
有时候你想修改远端仓库的简写名。比如你将女朋友的名字命名为远端仓库的简写名,然后你们分手了。这真是一个令人悲伤(欣喜)的故事。
$ git remote rename nvpengyou gaoyuanyuan
查看远端仓库列表。
$ git remote
gaoyuanyuan
origin
删除
一般来说,一个git项目有一个远端仓库就行了,其余的大多是临时性的。所以总有一天要删除它。
$ git remote rm horseshoe
查看远端仓库列表。
$ git remote
origin