掌握 Git 远程仓库,让团队协作更上一层楼

介绍下远程仓库的概念、常见的远程仓库以及常见的操作。

什么是远程仓库

目前,我们的版本库都是在自己的电脑上,并不方便给别人访问,更别说一起维护一个版本库了;如果我们的电脑关机了(或者坏了),岂不是别人就没法干活了?

因此,我们通常需要找一台服务器,存放我们的版本库;然后,其他人就可以访问并克隆这个原始的版本库,并且每个人的版本库都是完整的,不存在主次之分。

Git 仓库托管服务网站

如果为了学习 Git 而搭建一个 Git 服务器是没必要的,有很多网站都提供了 Git 仓库托管服务,我们可以注册后使用:

  • GitHub:全球最大的 Git 仓库托管服务网站,2008 年上线,为开源项目提供 Git 存储,无数开源项目迁移到了 GitHub,例如 JQueryPHPRuby
  • Gitee:由于 GitHub 是国外的,在国内有种不可抗力的因素导致经常访问失败,因此国内也上线了一个代码托管平台,那就是 Gitee
  • GitLab:在工作中,我们的项目大部分是公司内的,不太可能开源(例如银行内的项目,源代码保护的非常好),因此有必要公司自己内部搭建一个 Git 仓库,通常使用的就是 GitLab,它是一个开源项目。

关于源代码保护,这里不得不提一下,大部分科技公司都是靠自己的项目来赚钱的,不太可能开源,而且开源了还有被发现漏洞和攻击的风险,所以一般都是用 GitLab 这种可以在内网使用的工具。读者可以参考下华为内是怎么保护的,我在国企工作过,可以说这些经历非常类似了:

百度、阿里、腾讯之类的大公司用 Git 吗?他们如何管理源代码? - 知乎 作者:jiakon

华为用的是 SVN。

SVN 的权限控制,可以控制到目录的。你可以访问到哪个级别的代码,都是可以控制的。

另外,以华为的内网安全措施,周身遍布摄像头,电脑遍布监控软件,访问外网严格受限,所有 USB 接口和网口贴封条,封条上还有什么镭射喷码之类的东西,封条被撕过是可以看出来的,安全管理员定期检查封条。根据安全等级区分绿区、黄区、红区,区域之间物理隔离,访问安全级别更高的区要通过专用远程登录软件,连截屏软件都被禁用。这是一个为了信息安全不惜牺牲效率的企业。这么严格的管控措施,你还想偷偷拷走代码?当然,曾经有神人做到了,比如通过示波器的 USB 口。现在的安全措施又比我在的时候严格了很多。这种事情越来越不可能发生了。

一个在华为待了 9 年的人,离职时都忍痛放弃拷走多年的照片,这是即使走流程申请都几乎不可能做到的事情。谁知道,你图片中是否隐藏了什么保密信息呢?

另外,即使你不小心拥有了不该有的权限,你下载了一些不该拥有的文件。电脑上还有个监控软件,叫关键资产扫描。这个软件也是不能关掉的。安装时,会全盘扫描一次你的电脑,每周还会定时全盘扫描一次,看看你电脑中是否有超出你权限之外的文档和代码,如果有,要么删除,要么申请权限。

有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目录下。因为 Git 是为 Linux 源代码托管而开发的,所以 Git 也继承了开源社区的精神,不支持权限控制。不过,因为 Git 支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite 就是这个工具。--引自 搭建 Git 服务器 - 廖雪峰的官方网站

另外,如果你访问不了 GitHub,可能是某种不可抗力的问题,请自行搜索解决,可参考我的下一篇博客。

创建公钥和私钥

我们本地 Git 仓库和远程仓库之间的传输是通过 SSH 协议加密的,因此需要创建公钥和私钥。

PS:公钥和私钥其实就是两个字符串,用于身份认证;我们先将公钥配置到远程仓库上,然后提交的时候通过 SSH 协议来加解密数据,验证我们的身份。感兴趣的同学可以学习下:非对称加密算法 - 廖雪峰的官方网站

Git 也支持其他协议,例如 HTTPS,但是不太安全,并且比较慢,较少使用。

打开命令行(或者 Git Bash),输入以下命令来创建 SSH Key:

$ ssh-keygen -t rsa -C "youremail@example.com"

注意邮箱换成你自己的,一路回车,使用默认值即可。

如果一切顺利的话,可以在用户主目录里找到 .ssh​ 目录,里面有 id_rsa​ 和 id_rsa.pub​ 两个文件。

PS:对于 Windows 用户来说,用户主目录是 C:\Users\你的用户名​,例如我的是:

对于 Linux 用户:

cd ~/.ssh
ssh-kengen -t -a rsa

这两个就是 SSH Key 的秘钥对,可以右键用记事本之类的工具打开。id_rsa ​里的内容是私钥,不能泄露出去,id_rsa.pub ​里的内容是公钥,可以放心地告诉任何人。

远程仓库就是通过公钥来识别你的身份的,对于那些没有对应私钥的人来说,是不能修改你的仓库里的内容的。

在远程仓库里配置公钥

这里假设读者已注册好(注册就不用演示了吧 😅)

对于 Gitee

登录后,在右上角点击设置

然后在左侧菜单栏选择 SSH 公钥,然后在右侧输入公钥的标题(自己取个方便记的名字),然后粘贴公钥即可:

对于 GitHub

和 Gitee 类似,登录后右上角选择设置:

然后在左侧菜单栏选择 SSH 公钥,然后选择 new ssh key:

在右侧输入公钥的标题(自己取个方便记的名字),粘贴公钥即可:

对于 GitLab 而言

GitLab 通常是需要管理员添加用户后,才可以登录。登录后同理,右上角-设置:

左侧菜单里--SSH 公钥:

补充说明

  1. 注意不要将敏感信息提交到版本库里,以免泄漏

  2. 大多数 Git 托管服务,例如 GitHub、Gitee 和 GitLab 都支持添加多个 key。例如笔者有两台笔记本,1 个台式机,有时候在笔记本开发,有时候在台式机上开发,这时候可以分别在两台电脑上生成公钥和私钥并添加到远程仓库,这样几台电脑都可以直接访问和修改远程的版本库

  3. Git 服务器还可以设置是否开源,如果你的代码不想被别人看到,或者想晚点开源,可以设置私有(别人不可读,也不可写)。例如 Gitee:

  4. 点赞是个好习惯 😄,我们有时候能看到某某项目在 GitHub 有成千上万的点赞,赞越多,表明受欢迎更高。

Gitee 在 2022-5-18 日出了政策,开源项目必须要审核,感兴趣的同学可参考:突发!Gitee 仓库开源必须审核,官方迅速回应 - 知乎

创建远程库

我们之前都是在本地创建了 Git 仓库,现在我们想将本地的版本库推送到 Git 服务器上,这样既可以作为一个备份,也可以被别人访问到,为将来协同开发提供了可能~

首先,我们得在 Git 服务器上创建一个仓库,然后才能将本地仓库和远程仓库关联起来。

在 GitHub 创建仓库

登录后,在右上角的 + 号里选择创建仓库

然后我们输入 Git 仓库的名字,和相关描述、是否公私有等。注意其他选项请保持默认,我们需要的是一个空的仓库(相当于在一个空目录里使用 git init​):

然后我们就创建好了!

在 Gitee 创建仓库

登录后,在右上角的加号里选择新建仓库:

然后也是一样,需要填写创建仓库的信息:

此时我们就创建好啦~:

关联本地仓库和远程库

我们需要将本地仓库 和远程仓库关联起来,这样我们才能将本地仓库推送到远程仓库上。我们可以将本地仓库和多个远程仓库关联起来。

不知道你有没注意,在创建好仓库后,在项目底部有很贴心的提示,告诉我们如何关联:

--GitHub 的提示:
$ git remote add origin git@github.com:Peter-JXL/LearnGit.git

--Gitee 的提示:
$ git remote add origin git@gitee.com:peterjxl/LearnGit.git

remote add 就是只添加一个远程库,origin 是我们给远程仓库的命名(默认是 origin,关联一个远程库时必须给远程库指定一个名字。为什么要命名?因为我们可能有多个远程仓库,需要起不同的名字来区分),后面跟的是远程仓库的地址。

输入以下命令,就可以将本地仓库和两个远程仓库关联起来(我这里给两个远程仓库分别命名为 Gitee 和 GitHub):

$ git remote add gitee git@gitee.com:peterjxl/LearnGit.git
$ git remote add github git@github.com:Peter-JXL/LearnGit.git

注意,如果你也创建了远程仓库,在关联的时候需要输入自己的远程仓库地址,而不是直接 copy 我的

接下来,我们就可以推送本地仓库内容到远程仓库了,我这里分别推送了两个远程仓库:

$ git push -u github master
Enumerating objects: 30, done.
Counting objects: 100% (30/30), done.
Delta compression using up to 20 threads
Compressing objects: 100% (21/21), done.
Writing objects: 100% (30/30), 2.69 KiB | 688.00 KiB/s, done.
Total 30 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), done.
To github.com:Peter-JXL/LearnGit.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'github'.



$ git push -u gitee master
Enumerating objects: 30, done.
Counting objects: 100% (30/30), done.
Delta compression using up to 20 threads
Compressing objects: 100% (21/21), done.
Writing objects: 100% (30/30), 2.69 KiB | 688.00 KiB/s, done.
Total 30 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:peterjxl/LearnGit.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'gitee'.

git push ​命令,实际上是把当前分支 master ​推送到远程。由于远程库是空的,我们第一次推送 master ​分支时,加上了 -u ​参数,Git 不但会把本地的 master ​分支内容推送的远程新的 master ​分支,还会把本地的 master ​分支和远程的 master ​分支关联起来。

在以后的推送或者拉取时就可以简化命令,不用带-u 参数了:

$ git push github
$ git push gitee

我们可以刷新下远程仓库的页面,此时可以看到都有内容啦 😎😎:

即使在没有联网的情况下,我们也可以先在本地开发,联网后再推送即可完成同步,这就是分布式版本系统的好处。

管理远程仓库

如何查看本地仓库关联多少个远程库呢?可以用 git remove -v ​命令:

$ git remote -v
gitee   git@gitee.com:peterjxl/LearnGit.git (fetch)
gitee   git@gitee.com:peterjxl/LearnGit.git (push)
github  git@github.com:Peter-JXL/LearnGit.git (fetch)
github  git@github.com:Peter-JXL/LearnGit.git (push)

为什么一个仓库有两个输出?末尾的 fetch 表明是拉取,push 表明是推送,我们后续再说

如果我们添加错了远程仓库呢?可以使用 git remote rm 仓库名​ 删除:

$ git remote rm github

此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到代码托管平台,在后台页面找到删除按钮再删除:

更多使用 git remote 的用法,可以使用 -h 参数来查看:

$ git remote -h
usage: git remote [-v | --verbose]
   or: git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>
   or: git remote rename <old> <new>
   or: git remote remove <name>
   or: git remote set-head <name> (-a | --auto | -d | --delete | <branch>)
   or: git remote [-v | --verbose] show [-n] <name>
   or: git remote prune [-n | --dry-run] <name>
   or: git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]
   or: git remote set-branches [--add] <name> <branch>...
   or: git remote get-url [--push] [--all] <name>
   or: git remote set-url [--push] <name> <newurl> [<oldurl>]
   or: git remote set-url --add <name> <newurl>
   or: git remote set-url --delete <name> <url>

    -v, --verbose         be verbose; must be placed before a subcommand

可以看到,改名可以使用 git remote rename <old> <new>​。

从远程仓库克隆

之前我们是先本地创建了仓库,然后再创建的远程仓库,并关联。

然而,实际情况是我们经常是维护旧项目,即已经有了远程仓库,此时我们需要从远程仓库里下载;

为了模拟并实践这种情况,我们假设目前没有本地仓库(我们换一个本地目录),然后使用 git clone 远程仓库地址 下载:

$ git clone git@github.com:Peter-JXL/LearnGit.git
Cloning into 'LearnGit'...
remote: Enumerating objects: 30, done.
remote: Counting objects: 100% (30/30), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 30 (delta 2), reused 30 (delta 2), pack-reused 0
Receiving objects: 100% (30/30), done.
Resolving deltas: 100% (2/2), done.


$ cd LearnGit
$ ls
d-----        2023-01-13     22:42                1-diffAndPath
d-----        2023-01-13     22:42                2-versionControl

其他人下载的方式也是一样的,自己选择一个目录后下载。

那么如何获取一个仓库的地址呢?可以在代码托管平台里复制。

对于 Gitee:

对于 GitHub:

一个仓库应该有的东西

一个仓库,除了有代码之外,应该还有这些东西:

  1. 说明文档 readme.md,用于展示在仓库首页
  2. LICENSE:项目的许可证,例如是否别人随意的使用你的项目
  3. .gitignore​:一个 Git 配置文件,用于说明哪些文件不用纳入到 Git 管理,我们后续再说

readme.md

以说明文档为例:我们打开我们的 Git 仓库

可以看到直接就是一堆目录,外人点进来是不知道你这个项目是干嘛的。并且 Github 也提示我们

Help people interested in this repository understand your project by adding a README.

因此,我们可以尝试给该仓库添加一个 readme.md 文档。我们创建一个 Markdown 文档,并添加到版本库后推送:

$ echo "This project is use to Learn Git" > readme.md
$ git commit -m "add readme.md"
$ git push gitee
$ git push github

然后我们查看远程仓库:

当然,我们写的比较简单,后续会逐步完善;一般大型项目的说明文档都写的很完善的,例如 jQuery

LICENSE

关于开源证书的问题,可以参考阮一峰老师的博客:开源许可证教程 - 阮一峰的网络日志,这里引用一部分内容:

开源许可证是一种法律许可。通过它,版权拥有人明确允许,用户可以免费地使用、修改、共享版权软件。

版权法默认禁止共享,也就是说,没有许可证的软件,就等同于保留版权,虽然开源了,用户只能看看源码,不能用,一用就会侵犯版权。所以软件开源的话,必须明确地授予用户开源许可证。

.gitignore

有些时候,你必须把某些文件放到 Git 工作目录中,但又不能提交它们,比如:

Git 考虑到了这一点,我们只需在 Git 工作区的根目录下创建一个特殊的 .gitignore ​文本文件,然后把要忽略的文件名填进去(支持正则),Git 就会自动忽略这些文件(不追踪 track)。

例如,我们进行 Java 开发,需要忽略所有的.class 文件,可以这样写:

*.class

想要忽略某个文件,只需写上文件名即可:

Desktop.ini
Thumbs.db

最后一步就是把 .gitignore ​也提交到 Git 了,并且可以对 .gitignore ​做版本管理!

我们来实践下:

> echo "*.class" > .gitignore
> cat .gitignore
*.class

然后我们可以新建一个 class 文件,并且查看仓库状态:

$ echo "fuk" > Fuk.class

$ ll
total 10
drwxr-xr-x 1 peterjxl 197121    0  1月 11 07:37 1-diffAndPath/
drwxr-xr-x 1 peterjxl 197121    0  1月 14 07:19 2-versionControl/
-rw-r--r-- 1 peterjxl 197121    4  1月 14 09:31 Fuk.class
-rw-r--r-- 1 peterjxl 197121   33  1月 13 22:53 readme.md

$ git st
On branch master
Your branch is ahead of 'gitee/master' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

有些时候,你想添加一个文件到 Git,但发现添加不了,原因是这个文件被 .gitignore ​忽略了:

$ git add Fuk.class
The following paths are ignored by one of your .gitignore files:
Fuk.class
hint: Use -f if you really want to add them.
hint: Turn this message off by running
hint: "git config advice.addIgnoredFile fals

Git 告诉我们,如果你确实想添加该文件,可以用 -f ​强制添加到 Git:

$ git add -f Fuk.class

或者你发现,可能是 .gitignore ​写得有问题,需要找出来到底哪个规则写错了,可以用 git check-ignore ​命令检查:

$ git check-ignore -v Fuk.class
.gitignore:1:*.class    Fuk.class

Git 会告诉我们,.gitignore ​的第 1 行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。

git check-ignore -v . 检查当前文件夹被哪一个配置忽略了

git check-ignore -v fileName 检查指定的文件被哪一个配置忽略了

还有些时候,当我们编写了规则排除了部分文件时:

# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class

但是我们发现 .* ​这个规则把 .gitignore ​也排除了,并且 App.class ​需要被添加到版本库,但是被 *.class ​规则排除了。

虽然可以用 git add -f ​强制添加进去,但有强迫症的童鞋还是希望不要破坏 .gitignore ​规则,这个时候,可以添加两条例外规则:

# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class

# 不排除.gitignore和App.class:
!.gitignore
!App.class

把指定文件排除在 .gitignore ​规则外的写法就是 !​+ 文件名,所以,只需把例外文件添加进去即可。

可以通过 https://gitignore.itranswarp.com 在线生成 .gitignore ​文件。

其实我们在创建远程仓库的时候,一般也会提醒我们是否创建这些文件,读者可以回顾下我们创建远程仓库时的界面:

协同开发

即使是开源项目,也不是任何人都可以随意修改你的代码,万一有人不小心将所有文件删除了呢?或者随意提交了几个 bug 上去。开源意味着人人都能获取,但修改的话需要经过作者同意之后(GitHub、Gitee 和 GitLab 都可以提出这样的申请),才能修改。

一般来说,一个项目可以由作者设置多个开发者,这些开发者对仓库有较大的权限,可以直接通过 git add​ 和 git commit​ 等命令修改代码。

例如本博客的 Gitee 项目,可以在管理界面里邀请别人,这样别人就可以来开发和维护项目了。

而非本仓库的人员,可以先 fork 项目(右上角),自己拥有 Fork 后的仓库的读写权限,然后通过提出 pull request,来给官方仓库做出贡献:

在公司内开发的话,我们一般都是先找项目管理员,配置好权限后,才可以通过远程仓库拉去代码,然后开发,开发完后提交到远程仓库。

小结

本文主要介绍了如下内容:

  • 什么是远程仓库

  • 常见的 Git 仓库托管服务网站:GitHub,Gitee 和 GitLab

  • 创建远程仓库:登录后,点击右上角加号输入相关信息即可

  • 创建和配置公钥和私钥

  • 关联本地仓库和远程仓库:git remote add 远程仓库名 远程仓库地址

  • 管理远程仓库

    • 推送到远程仓库:git push -u gitee master​,git push 仓库名
    • 查看远程仓库信息:git remote -v
    • 删除远程仓库:git remote rm 仓库名
  • 从远程仓库克隆:git clone 仓库地址

  • 一个仓库里应该有的文件(标配):

    • 说明文档 readme.md,使用 Markdown 语法
    • 许可证 LICENSE,
    • 配置文件 .gitignore​​。git add -f​​ 强制添加, git check-ignore -v 文件名​​检查配置

内容比较多,没必要一次看完,每次看一点也是可以的。

推荐阅读

15 年封神,GitHub 开发者破亿!这个滋养了全世界码农的网站,已成传奇

posted @ 2024-09-26 10:28  peterjxl  阅读(99)  评论(0编辑  收藏  举报