本篇文章,是基于我自用Windows(Win10)系统当做示例演示
Git的远程仓库
之前我们一直在探讨 Git 的一些命令,也提及了仓库的概念。如果只是在一个仓库里管理文件历史,Git 和 SVN 真没啥区别。
Git 是分布式版本控制系统,同一个 Git 仓库,可以分布到不同的机器上。怎么分布呢?最早,肯定只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
你肯定会想,至少需要两台机器才能玩远程库不是?但是我只有一台电脑,怎么玩?
其实一台电脑上也是可以克隆多个版本库的,只要不在同一个目录下。不过,现实生活中是不会有人这么傻的在一台电脑上搞几个远程库玩,因为一台电脑上搞几个远程库完全没有意义,而且硬盘挂了会导致所有库都挂掉,所以我也不告诉你在一台电脑上怎么克隆多个仓库。
实际情况往往是这样,找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
拥有一个 Git 远程仓库有很多种方式,比如 GitHub,或者 Gitee,等等很多,都可以白嫖的。如果你很有探索精神,完全可以自己搭建一台运行 Git 的服务器。
以GitHub为远程仓库
前提先说一下,现在是 Win10 环境下。
为了演示远程仓库,我还是选择了比较流行的 GitHub 为示例,演示远程仓库。为了具有时效性,特别指出这篇文章写于 2022年12月7号,因为谁知道过了三天半月的 GitHub 改版了,我这篇博文就成了误导新手的。所以各位还是在日期就近的原则,仅供参考。
首选,您必须有一个 GitHub 的账号才行,请自行注册就行(网站打不开?别急,多刷几次了,人家服务器在国外呢)。由于你的本地 Git 仓库和 GitHub 仓库之间的传输是通过 SSH 加密的,所以,需要一点设置:
第1步:创建 SSH Key。在用户主目录下,看看有没有.ssh
目录,如果有,再看看这个目录下有没有id_rsa
和id_rsa.pub
这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开 Shell(Windows 下打开 Git Bash,对不起,我觉得第1步的前提得安装 Git 吧),创建 SSH Key:
$ ssh-keygen -t rsa -C "youremail@example.com"
需要注意的是,youremail@example.com 应该改成您自己的邮箱,之后会要求确认路径和输入密码,我们这使用默认的一路回车就行。
比如我这里:
$ ssh-keygen -t rsa -C "lee@163.com"
如果执行成功的话,会在我之前说的.ssh
目录下生成id_rsa
和id_rsa.pub
这两个文件,其中id_rsa
是私钥,id_rsa.pub
是公钥。
第2步:登陆 GitHub,页面右上角头像小图标,打开“Settings”,“SSH and GPG keys”页面:
直接点击“New SSH key”,进入。填上任意 Title,在 Key 文本框里粘贴id_rsa.pub
文件的内容:
点“Add Key”,你就应该看到已经添加的 Key 了。
为什么 GitHub 需要 SSH Key 呢?因为 GitHub 需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而 Git 支持 SSH 协议,所以,GitHub 只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub 允许你添加多个 Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的 Key 都添加到 GitHub,就可以在每台电脑上往 GitHub 推送了。
在GitHub上创建仓库
现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。
首先,登录 GitHub,然后,在右上角的“小加号”找到“New repository”按钮,创建一个新的仓库:
进入仓库创建界面,按常理里面就一个必填项“Repository name”,填写上你想起的仓库名,其它的默认就好。我这里“Repository name”取了一个test_git_rep
,按照常理它会验证您是否唯一命名。这里就不在截图了,但凡你和我一样是一个半斤八两一样的英语水平,您都能找到填写的地方。
点击页面最下方的“Create repository”按钮,就成功地创建了一个新的Git仓库:
从给出的提示信息,会发现,远程仓库提供了两种(HTTPS和SSH)远程连接方式,我们这里还是选中一开始的就设置的“SSH”模式(您非要用 HTTPS 形式的,咱也拦不住)。
目前,在 GitHub上 的这个test_git_rep
仓库还是空的,GitHub 告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到 GitHub 仓库。
从给出的提示中也可以知道,想远程连着这个仓库,其 SSH 地址是:git@github.com:lili40342/test_git_rep.git
再提醒一下,这个地址是我写博文演示用的,到时候,你还根据您自己设置对应您自己的仓库即可。
本地添加远程仓库
首先还是描述一下我的测试环境,安装好 Git(无脑安装即可,经验贴搜网络),Win10 下我在我自己的 E 盘下创建一个test_git_rep
文件夹,做为本机的一个仓库,在E:\test_git_rep
,打开”Git Bash“执行:
#Git Bash下执行的
$ git remote add origin git@github.com:lili40342/test_git_rep.git
再次提醒一下,这个 SSH 地址是我自己的测试地址,到时候您还得换成您自己的。你要是不换,你可是关联成我的这远程仓库了,关联没有问题,但是你以后推送是推不上去的,因为你的 SSH Key 公钥不在我的账户列表中。
添加后,远程库的名字就是origin
,这是 Git 默认的叫法,也可以改成别的(至今我没见过改它的),但是origin
这个名字一看就知道是远程库。
另外,如果你出现这么一个错误报错“fatal: not a git repository (or any of the parent directories): .git”,那是因为你这个文件夹并不是 Git 版本库,需要初始化才行。所以在执行命令前需要确定你的测试地址的文件夹目录是不是已经执行了git init
进行了 Git 仓库的初始化。
执行上面命令成功以后,可以利用下年的命令查看一下有哪些远程仓库:
#Git Bash下执行的
$ git remote -v
#或者 显示某个仓库的信息
$ git remote show [remote]
#[remote]是远程仓库名origin,或者是SSH地址或者是HTTPS地址
到这里有人问我,我本地的这个仓库和远程的仓库的名字,能不能不是一样的?
当然可以,只要你能分的清记得牢,没问题
但是一般情况下,大家习惯上统一本地和远程的仓库名字,便于记忆和管理
继续,人为的造几个文件呗(我个人造了一个test.java
文件),这时就可以把本地库的所有内容推送到远程库上:
#推送命令为:git push <远程主机名> <本地分支名>:<远程分支名>
#如果本地分支名与远程分支名相同,则可以省略冒号:git push <远程主机名> <本地分支名>
#一般情况下,都是将本地分支名和远程分支名统一一致即可
$ git push origin master
执行上面的命令,别忘了先把你造的那几个文件git add
和git commit
了,当然在这里之前,别忘了配置您的git config
中的“user”和“email”。
命令执行的时候,会有提示,输入yes
即可(有兴趣自行看看那个提示是啥意思),或者你可直接用$ git push -u origin master
,因为远程仓库有可能是空的。
把本地库的内容推送到远程,用git push
命令,实际上是把当前分支master
推送到远程。Git 不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
然后切到您自己的 GitHub 对应的仓库上,刷新一下,你就可以看到您刚刚推送上的文件。
从现在起,只要本地作了提交,就可以通过命令$ git push origin master
把本地master
分支的最新修改推送至GitHub,现在,你就拥有了真正的分布式版本库!
还有一个地方,需要说明一下。GitHub 早就把默认的master
分支改成了默认main
分支,虽然有点不太舒服,子不过是换了个名词而已,所以即使你推送的是master
分支,到了 GitHub 那里它会默认认为是main
分支。
SSH警告
当你第一次使用 Git的clone
或者push
命令连接 GitHub 时,会得到一个警告:
The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?
这是因为 Git 使用 SSH 连接,而 SSH 连接在第一次验证 GitHub 服务器的 Key 时,需要你确认 GitHub 的 Key 的指纹信息是否真的来自 GitHub 的服务器,输入yes
回车即可。这个警告只会出现一次,后面的操作就不会有任何警告了。当然没有这个警告,那就不用管它了。
删除远程仓库
如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm <name>
命令。使用前,建议先用git remote -v
查看远程库信息:
#Git Bash下执行的
$ git remote -v
origin git@github.com:lili40342/test_git_rep.git (fetch)
origin git@github.com:lili40342/test_git_rep.git (push)
以上,这是我本地刚才模拟测试的时候E:\test_git_rep
本地测试仓库中的远程仓库。然后,根据名字删除,比如删除origin
:
#Git Bash下执行的
$ git remote rm origin
此处的“删除”其实是解除了本地和远程的绑定关系(再通过git remote -v
就查不到远程仓库了),并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到 GitHub,在后台页面找到删除按钮再删除。
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!
从远程库克隆
上次我们讲了先有本地库,后有远程库的时候,是如何关联远程库。
现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。
首先,登录 GitHub,创建一个新的仓库,名字叫test_git_rep_plus
:
我们勾选Add a README file
,这样 GitHub 会自动为我们创建一个README.md
文件。创建完毕后,可以在新建的仓库中看到这个README.md
文件。
现在,远程库已经准备好了,本地我继续准备一个测试的文件目录,作者本人选在E:\test_git_rep_plus
目录下了,打开”Git Bash“,下一步是用命令git clone
克隆一个本地库:
#Git Bash下执行的
$ git clone git@github.com:lili40342/test_git_rep_plus.git
Cloning into 'test_git_rep_plus'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
其中“git@github.com:lili40342/test_git_rep_plus.git”是我刚才创建新的 GitHub 仓库的 SSH 地址,还是那句话您要自己测试得换成自己的才对。
执行完之后,你会发现在E:\test_git_rep_plus
目录下已经将远程仓库的文件“克隆”到您的本地了。
如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。
抓取分支
刚才,我们已经从远程仓库“clone”带本地了。默认情况下,只能看到本地的master
分支。这里不得不提一下,由于众所周知的原因,GitHub 修改默认的分支为 main 后,所以第一次“clone”下来的,并不是默认的master
分支了,取而代之的是main
分支。也这是我不太爱用 GitHub 演示远程仓库的原因,它与一开始 Git 的习惯默认master
分支不太一样了,有点别扭,不过不要紧,换了个名字而已。
不信可以用git branch
命令看看:
#Git Bash下执行的
* main
现在,你要在dev
分支上开发,按照一般的操作,就是在本地的仓库上创建一个dev
分支。那么可能会有两种情况:
第1种情况,远程仓库存在dev
分支,这里我们就假设它存在。我们认为的去 GitHub 上的仓库创建一个dev
分支。假设我已经创建好了(如何创建?搜搜网络吧,这里不截图演示了),于是用这个命令查看远程库是否有dev
分支:
#Git Bash下执行的
#先更新抓取一下远程仓库在本地仓库的缓存
$ git fetch origin
From github.com:lili40342/test_git_rep_plus
* [new branch] dev -> origin/dev
#再查看远程的仓库
$ git branch -r
origin/HEAD -> origin/main
origin/dev
origin/main
如上,main
分支就是 GitHub 由 master
改成的main
分支,其实就是master
分支。
既然远程仓库已经有dev
分支了,那么我们就可以拉取远程仓库的dev
分支了:
#Git Bash下执行的
$ git checkout -b dev origin/dev
Switched to a new branch 'dev'
branch 'dev' set up to track 'origin/dev'.
上面的意思就是,创建本地的dev
分支并关联远程仓库的dev
分支。一般情况下,默认本地分支应该与远程分支保持同命名,以便好管理。这个时候可以通过git branch
查看本地已经切换到dev
分支上:
$ git branch
* dev
main
其中,git checkout -b dev origin/dev
是拉取dev
后本地直接切换到dev
分支上,如果用git fetch origin dev
,只是把远程仓库的dev
拉取到本地,本地并不会自动切换,需要手动切换分支。
第2种情况,远程仓库并没有dev
分支,那么我们可以在本地自创建一个dev
分支,到时候推送到远程仓库。那这种就很简单了,本地先创建新的dev
分支:
#Git Bash下执行的
#创建分支
$ git branch dev
#推送到远程仓库
$ git push origin dev
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'dev' on GitHub by visiting:
remote: https://github.com/lili40342/test_git_rep_plus/pull/new/dev
remote:
To github.com:lili40342/test_git_rep_plus.git
* [new branch] dev -> dev
如上,这样就可以切换到本地的dev
分支开始干活了。
推送分支
继续。不管您是第1种情况,还是第2种情况,到此可以在dev
下面干活了。我们模拟一下增加了新文件:
#Git Bash下执行的
#先看看再哪个分支上
$ git branch
* dev
main
#随便增加个文件
$ touch Hello.py
#add并commit
$ git add Hello.py
$ git commit -m "本地仓库提交Hello.py" #这里的注释用的双引号,因为是在windows系统下
[dev e84de30] 本地仓库提交Hello.py
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 Hello.py
提交成功,此时,只是在本地的dev
中提交了,远程仓库中并没有新提交的数据。下一步我们将本地dev
新增加的数据,提交到远程仓库对应的dev
分支中:
#Git Bash下执行的
$ git push origin dev
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 295 bytes | 295.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:lili40342/test_git_rep_plus.git
77a42f0..e84de30 dev -> dev
转去看看 GitHub 对应的仓库,刷新一下即可看到你从本地推送来的新数据。
多人协作
往往在开发过程中,不会只有你一个人在本地操作,推送到远程仓库。肯定会有第2个人,第3个人,甚至10多个人一起,多人协作开发。就会出现您修改了一个文件,另外一个人也修改了这个文件的情况。
假设 A 已经修改了 test.java
文件,并本地提交也push
到远程仓库中了。B 也修改了,他也本地提交之后,他晚于 A 也准备push
到远程仓库,势必会造成版本冲突。解决这种问题,应该是不管谁要push
,在push
前要先用git pull
把最新的提交从origin/dev
抓下来,然后,在本地合并,解决冲突,再推送git pull
。
拉取数据:
$ git pull origin dev
总结一下
友情提示,在 GitHub 上免费托管的 Git 仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。
如果你不想让别人看到 Git 库,有两个办法,一个是交点保护费,让 GitHub 把公开的仓库变成私有的,这样别人就看不见了(不可读更不可写)。另一个办法是自己动手,搭一个 Git 服务器,因为是你自己的 Git 服务器,所以别人也是看不见的,至于如何自己搭建一台 Git 服务器,各位自行搜网络经验贴吧,作者表示没兴趣搞,那都是运维的事吧,我本人并不是运维。不爱干,嘿。
最后,我写了这么多,好像通过 TortoiseGit 都能搞定?是的,没错。