远程仓库
远程( remote )版本库也叫上游( origin )版本库。
通常我们并不常亲自建立远程仓库,而是委托给『第三方』。
常见的操作是,先在第三方上创建『远程 Git Repository』,然后复制( Clone )出一个『本地 Git Repository』。
1. 在托管网站上创建远程仓库
常见的代码托管仓库有:
- 国外:github、gitlab
- 国内:gitee、coding、云效
- 自建私服:gogs、gitea、gitlab
在托管网站上创建项目后,通常项目目录下是空的。
托管网站上所创建的项目就是所谓的「远程( remote )仓库」、也叫「上游( origin )仓库」。
从它所扮演的角色、承担的功能来讲,也有人习惯性称之为「中央仓库*」。
逻辑上,远程仓库的仓库名( 项目名 )和你的本地仓库的仓库名( 项目名 )应该是一样的。这虽然看起来是一句废话,但是,实际上你如果硬是要弄得不一样,也是可以的...
远程仓库作为一个中间的「桥梁」就可以在多台电脑之间「传递」项目文件。无论,这多台电脑是你一个人的,还是不同人的。
关联本地仓库和远程仓库
第 1 步:创建远程仓库
在托管网站上创建一个和你本地仓库同名的仓库。
略。
第 2 步:为本地仓库添加远程仓库地址
进入你的本地的 git 仓库(也就是你的项目目录),为它添加远程仓库( 也就是上游仓库 )的网址。然后执行 git push 命令将本地仓库的内容( 和历史记录 )「上传」到远程仓库。
cd <本地仓库目录> # git remote remove origin git remote add origin <远程仓库中的网址> git push -u origin "master"
上面
git push
命令中的-u
是--set-upstream
的简写。
本地仓库和远程仓库之间的「关系」体现在 Git 的配置项的 origin 属性上。使用 git config -l
可以看到:
...
remote.origin.url=远程Git文档库地址
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
...
2. 远程仓库的网址
提前说明,远程仓库的网址有 2 种格式。
http/https 地址
一般情况下,上面的「远程仓库中的网址」是一个 http/https 的地址。http/https 地址形如:
https://gitee.com/hemiao3000/java-note-dist-vuepress2.git
当你执行 git push
命令「上传」你的本地内容时,为了证明你自己的身份,托管网站会要求你提供「用户名/密码」来决定是否允许你的上传行为。
未来,每当你执行 git push
命令( 不光是它,还有其它一些命令也需要 )的时候,理论上你都要输入你的托管网站的用户名和密码。
图形化客户端有「记住密码」功能
绝大多数图形化的客户端工具( 例如,GitKraken、SourceTree 等 )都有记住密码的功能,能够在你执行相关操作时「帮」你输入密码,而无需你亲自、反复输入。
不过,你要记得,本质上这里每次 git push
命令是需要提供用户名/密码的,只不过不是你亲自输入罢了。
当然,你使用有 RememberMe 功能的客户端倒还好,如果你使用的是命令行,隔三岔五地就需要输入一次托管网站的用户名/密码也是很令人烦躁的事情。
SSH 地址
第二种远程网址格式是一个 SSH 的地址,它能「从根本上」帮你省掉输入托管网站用户名密码的环节。ssh 地址形如:
git@gitee.com:hemiao3000/java-note-dist-vuepress2.git
这种情况下你要通过,ssh-keygen 命令生成一对 SSH 公钥和私钥,并将公钥( 的内容 )「告知」托管网站。
这样,当你再执行 git push
( 或其它需要认证 )的命令时,托管网站能判断地出当前的请求是来自于「你的电脑」,从而无需你输入托管网站的用户名和密码。
# 理论上『备注』的内容任意。不过通常是 2 种风格:
# - 你的邮箱,例如:hemiao3000@126.com
# - username@hostname,例如:root@192.172.0.16
ssh-keygen -t rsa -b 4096 -C "<备注>"
# 一路回车、回车、回车、回车...
查看生成的内容。复制粘贴它,后面要用到这个内容。
# 或者在你的用户加目录下找到它,用任意文本编辑器打开它也行。
cat ~/.ssh/id_rsa.pub
在托管网站上进行配置,将 id_rsa.pub 的内容配置到托管网站的对应设置中。
补充
ssh-keygen 的参数除了 -t rsa
之外,还可以其他的( 代表使用不同的加密算法 ),例如 -t ed25519
。
3. 克隆远程仓库至本地
如果作为项目团队成员,你需要去『初次下载』组长在托管网站( 也就是逻辑上的中央仓库 )上所所创建的项目时,你要执行的是 git clone
命令。
git clone <远程文档库的路径> <本地文档库的文件夹名称>
更具体的的格式为:
git clone <http://Web服务器地址/远程文档库路径> <本地文档库名称>
例如:
git clone <项目的 http 网址>
# 或
git clone <项目的 ssh 网址>
理论上,git clone
命令一个项目通常只会执行一次,因为它代表的是从无到有的「第一次下载」,后续的「下载」实际上是「更新、拉取」,使用的是 git pull
/ git fetch
命令。
4. 推送
当我们完成对本地文档库的修改,可以将这些修改『推送』到远程 Git 仓库:
git push origin [分支名称]
git push
有 2 种模式:
推送『当前』分支,而非本地仓库的所有分支。配置:
# 推荐这种模式,更安全、稳妥,不会手滑出错。 git config --global push.default simple
推送本地『所有』分支,而不仅仅是当前分支。配置:
git config --global push.default matching
另外,无论哪种传送模式,只要执行 git push --all
都是推送所有分支,无视你的全局配置。
5. fetch 和 pull
如果你有一个远程 Git 分支,比如在 GitHub 上的分支,当远程分支上包含当前分支没有的提交时,可以使用取回。
比如,当合并了另一个分支或你的同事推送了一个快速修复时。
通过在这个远程分支上执行 git fetch
,我们就可在本地获取这些修改。这不会以任何方式影响你的本地分支:fetch 只是单纯地下载新的数据而已 。
现在我们可以看到自上次推送以来的所有修改了。这些新数据也已经在本地了,我们可以决定用这些新数据做什么了。
git pull
逻辑上是两个命令的组合:git fetch
+ git merge
。
6. 大道理、小细节和套话
xxx 只和 xxx 玩,yyy 只和 yyy 玩:
当你要推送( push,逻辑上就是上传 )本地的 xxx 分支时,你上传的目的地一定是远程的 xxx 分支;
当你要拉取( push,逻辑上就是下载 )远程的 yyy 分支时,你下载的目的地一定是本地的 yyy 分支;
理论上虽然可以,但是实际上我们并不会让本地的 xxx 分支和远程的 yyy 分支有推拉关系。即,本地 xxx 分支只和远程 xxx 分支『玩』,本地 yyy 分支只和远程的 yyy 分支『玩』。
推拉( push / pull )都是在更新:
推送(push)操作的执行的潜在前提是:你的本地 xxx 分支上的代码一定更『新』(版本更高),否则,你为什么要上传呢?
拉取(pull)操作的执行的潜在前提是:你的远程 xxx 分支上的代码一定更『新』(版本更高),否则,你为什么要下载呢?
推拉都是在更新,只是『方向』不同:推送,是用本地 xxx 分支更新远程 xxx 分支;拉取,是用远程 xxx 分支更新本地 xxx 分支。
合理使用『简称』少费口舌:
通过
git push
命令推送本地 xxx 分支代码到远程 xxx 分支,实现远程 xxx 分支的代码的更新,简称:通过推送 xxx 分支来更新远程 xxx 分支。通过
git pull
命令拉取远程 yyy 分支代码到本地 yyy 分支,实现本地 yyy 分支的代码的更新,简称:通过拉取 yyy 分支来更新本地 yyy 分支。故意推拉『旧代码』是为了放弃:
可以推送( 上传 )旧代码,在此之前,你的远程 xxx 分支的代码更新,版本更高,而你推送( 上传 )的旧代码会覆盖掉远程的新代码;
也可以拉取( 下载 )旧代码,在此之前,你的本地 yyy 分支的代码更新,版本更高,而你拉取( 下载 )的旧代码会覆盖掉本地新代码;
通常情况下,你不太可能会用旧代码更新新代码,如果你这么干了,意味着你是想废弃新代码中『新』的那部分内容。