目录
- 安装 Git
- 设置 Git
- 开始使用 Git
- 远程仓库使用
- 服务器/本机搭建 Git
- Ubuntu 使用 ssh 远程连接电脑
一、安装 Git
-
MacOS:下载 Xcode 时会附带下载 git
-
Ubuntu:使用命令行进行下载
1
2
3
4
5
6
7Maybe you need update before you install
sudo apt update
If there are some problems during your update
you can check your sources.list and replace a new mirrows source
sudo apt install git
you can check if the installation is success
git --version
二、设置你的 Git
在团队合作中,我们每一次提交(git commit)都应该记录有作者的信息(姓名、电邮等)因此我们需要先设定一下自己的姓名和电邮。
1 | git config --global user.name "MyName" |
global
:表示全局设定。添加后我们可以使用命令行查看我们设定的内容:
1 | git config --list |
这些配置信息都可以在 Git 的隐藏文档中查看
1 | we can use editor to open this config file |
一些冷知识:
-
Git 支持利用 alias 功能代替复杂的命令
1
git config --global alias.st status
-
有时候我们希望 Git 去忽略空白的变化,这个时候你需要在你的设置中加入
1
git config --global apply.whitespace nowarm
PS:具体还没操作过,这个暂时忽略吧 😄
-
Git 预设输出时没有颜色的,我们可以让它输出的时候加上颜色帮助我们阅读。
1
git config --global color.ui true
三、开始使用 Git
1、建立仓库
Git 作为一个分布式管理代码的方案,我们需要在本地建立一个仓库(Repository),这个仓库是负责存放我们的代码。作为一个用户,我们可以自己新建一个仓库或者复制别人的仓库。
-
自己新建一个新的仓库
新建一个仓库前,你需要定义一个文件夹来作为仓库。使用 git 命令进行初始化
1
2
3
4
5
6
7create a new folder
init your Repository
git init <Folder_Name>
Another way to init Repository is get into your folder
then use git init
cd <Folder>
git init -
复制别人的仓库
当我们在 GitHub 或者 Gitee 上看到心动的程序,可以利用 Git 把代码抓取下来.
首先我们需要找到对应的程序位置,然后找到文件栏上方的 仓库地址 进行复制。
1
git clone [address]
Git 会将这个 Repository 下载到我们的电脑中。git clone 预设会将下载的 git 存储在同名的文件夹中。如果需要自己命名的话,可以在后面加上自己的命名:
1
git clone [address] <FileName>
2、Git 的基本操作
1) Git status
当我们在一个 Git 的 Repository 中,我们可以输入 git status
来检查当前 Git 的状态
1 | git status |
如果你看到了上面的信息,证明这是一个 崭新干净 的仓库,还没有被追踪或者修改。
On branch matser :当前正在名为 master 的分支(branch)上。
现在我们在这个目录下添加一个新的文件 “first.txt”,然后再查看一下仓库状态:
1 | cd <Repository> # get into your Repository |
我们可以看到这里多了个 Untrack files 的分类,这表示过去这个 Git Repository 并没有这个文件,first.txt 是一个未被追踪的文件。
2) Git add
如果我们要让 Git 能够跟踪这个档案的话。我们可以使用 git add
把它加入跟踪中:
1 | git add first.txt |
经过我们的 git add first.txt
后,文件就变成了 Change to commit,通常我们称这个状态叫做 stage ,修改过但还没使用 git add
的文档叫做 unstage 。
3) Git commit
Git commit
指的是把当前写好的文件提交,commit 是写程序过程中一个重要的动作,一个 commit 相当于给当前程序进度存档,让我们未来在需要的时候都可以回到这些存档的状态。
此时你会看到画面跳到 git 中设定的编辑画面:
这个窗口最上方的空行是要给你输入这次 commit 的信息。例如可以在这里写下 “Add first.txt file to test git function” 来表示本次提交的目的。建议每次 commit 时候都要写清楚 commit 的内容 这样会方便后续查看代码。也能让其他队员了解你在做什么。
写好 commit 后保存退出就会看到本次提交的变动。
【作者很懒,没有留下输出结果】
如果觉得每次跳出编辑器很麻烦,可以是用 commit 加上 -m 来快速提交
1 | git commit -m "Add first.txt to test git function." |
使用 git log
查看变动记录
1 | git log |
**补充:**还可以用 git log --stat
or git log -p
来看详情。
当你需要修改档案的时候,可以遵循以下流程:
1 | graph LR |
一般在完成一个阶段性小工作的时候就进行一次 commit 来及时保存程序开发进度。
冷知识: 某些文件我并不希望加入版本控制的跟踪中,例如说又个 Database 的 schema 或者是一些其他的 log 文件。这个时候你可以加入 .gitignore
来让 Git 忽略它。使用编辑器打开 .gitignore
档案
1 | vim .gitignore |
如果之前已经被跟踪的文件,是无法用 .gitignore
来完成的。需要将它们删除掉再 commit 后,使用 .gitignore
来设置忽略它们。
4)Git branch
分支(branch)应该是 Git 最重要的功能,在一个多人合作的开发过程中想要开发新功能或者修正某个 bug。当你完成开发后确认没问题再把它 merge(合并) 回主 Branch,如此便完成了新功能的开发或者 bug 的修正。
我们可以用 git branch
来列出所有的 branch 并告诉你正在哪一个当前所在 branch。如果我们需要开设一个新的分支 branch 名为 cat:
1 | git branch cat |
那么如何来切换当前的分支呢?我们利用 git checkout cat
来实现:
1 | git checkout cat |
如果我们在 cat 分支中继续开发并提交 commit。那么在 Git 中就会看到 cat 分支多了一个节点,这相当于对于 cat 的一个存档。此时 master 分支也继续开发,也 commit 了一一下,这是个时候就形成两个分支版本 master 和 cat。两者的版本从这里分开了,如果后续开发完成后,我们可以使用 git rebase
or git merge
来合并版本:
git rebase
:是基于分支 cat 提交后的版本git merge
:把当前各个分支一起融合
小结
git 的工作流程:
- 在仓库中有一个 master 主分支是大家开发好或者修好 bug 后合并回去的对象。所有需要新开发的新功能或者是修 bug 都是从主 branch 拉出一个新的 branch 进行工作。
- 当你完成一个阶段性任务后,将你刚刚所新增的内容使用 git add 加到 stage 的状态,然后 commit 加上信息
- 反复上一个操作直到这个 branch 的主要目的完成了,这个时候你离主 branch 已经有了一段时间,或者是确定主 branch 上已经有了新的 commit,使用 git rebase 将自己的分支整理然后使用 git merge 合并回 branch,反之直接用 git merge 将自己 branch 的内容合并回去。
3、Git reset 取消上一次操作
1)取消 merge
版本控制的最好好处是可以 无限后悔!,因此我们常常希望把已经暂存的档案、已经提交的 commit 或者是已经合并的 branch 取消修改,这个时候我们可以使用 git reset
这个指令来帮助我们,像现在我若是想要取消刚刚的 merge 动作,我只要:
1 | git reset --hard ORIG_HEAD |
2)取消已经暂存的文件
如果不小心把没有写完的文件 git add
加入 stage 了,那么后悔人可以用 git reset HEAD <file>
来取消这次 stage。
3)取消修改过的档案
如果后悔人想要完全放弃这次修改,回到上一个起点,可以使用 git checkout -- <file>
来恢复这个文件。
注意: 取消变更不会有任何信息,但这时你去看档案会发现他已经恢复成没有修改过的样子了。
4)修改上一次的 commit
如果后悔人由于手速太快,把 commit 的信息打错了,可以使用 git commit --amend
来帮助我们重新修改~
5)终极后悔人——强制恢复到上一个 commit 版本
作为一个 终极后悔人 ,有时候要放弃所有修改回到 commit 之前的状态,这个时候我们可以使用 git reset --hard HEAD
来恢复,HEAD 参数可以加上一些变化,比如 HEAD^ 表示目前版本的上一个版本;HEAD~2 是再上一个版本。
补充
在上面的用法中,你可能已经发现了后悔人在使用 git reset
的时候会加入 soft 和 hard 参数。一般来说,git reset
会把目前状态恢复到你想要回到的版本。但是如果不加参数的话,会把你做过的修改仍然保留,但是,加上了 --soft 参数,则会把做过的修改加入 stage 中,若是加上了 hard 参数则是把做过的修改完全删除,回到版本开始的样子。
四、远程仓库的使用
冷知识:「远程」仓库可以在你的本地主机上。「远程」未必表示仓库在网络或者互联网上,表示可以远程访问。
1、查看远程仓库
使用 git remote
命令,如果你已经 clone 了自己的仓库,那么至少会看到一个 origin (这个是 Git 给你克隆仓库服务器的默认名字)
1 | git clone [http] |
也可以是使用选项 -v 现实需要读写远程仓库使用的 Git 保存的简写与其对应的 URL
网上的 栗子🌰:
1 | git remote -v |
2、添加远程仓库
git remote add <shortname> <url>
添加一个新的 Git 仓库,同时指定一个方便使用的简写<shortname> :
1 | git remote |
现在我们可用字符串 pd 来代替整个 URL:
1 | get new data from remote Repository |
3、从远程仓库中抓取与拉取
从远程仓库获取数据:
1 | git fetch <remote> |
这个命令会访问远程的仓库,从中拉取所有你还没有的数据。执行完后,你就会拥有远程仓库中所有的信息,可以随时合并或者查看。
如果使用的是 clone
克隆一个仓库,命令会自动将其添加为远程仓库并默认为 “origin” 为简写。
git fetch origin
会抓取克隆后新推送的所有工作。必须注意 git fetch
命令只会将数据下载到你的本地仓库,它并不会自动合成或者修改你当前的工作。当准备好时你必须手动将其合并入你的工作。
4、推送到远程仓库
当你想分享你的项目时,必须将其推送到上游。这个命令很简单:git push <remote> <branch>
当你想要将 master 分支推送到 origin 服务器时,这个命令可以将你所做的备份到服务器:$ git push origin master
(猪油当你有克隆服务器的写入权限,并且之前没有人推送过时,这个命令才会生效,当你和其他人同时克隆,他们会先推送到上游然后你再推送到上游,你的推送毫无疑问会被拒绝,你必须先抓取他们的工作并合并到你的工作后才能推送!)
5、查看某个远程仓库
git remote show <remote>
如果想以一个特定的缩写名运行这个命令,例如 origin ,会看到下面类似的信息。
1 | git remote show origin |
它会列出远程仓库的 URL 与跟踪分支的信息。这些信息非常有用,他告诉你正处于 master 的分支,如果运行 git pull,就会抓取所有的远程引用,然后将远程 master 分支合并到本地 master 分支。
6、远程仓库的重命名与移除
git remote rename
重命名
注意,修改之后,git也会自动修改你所有远程跟踪的分支名字。那些过去引用上一个名字的分支现在会变成新的名字。
如果需要移除一个远程仓库——你已经从服务器上搬走了或者不想再使用某一个特定的镜像时候,或者不想再贡献了了——可以使用 git remote remove
or git remote rm
来移除。
注意⚠️:一旦使用这个方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。
五、在服务器 / 本机上搭建 Git (SSH)
1、创建 裸仓库
在开设 Git 服务器前,需要把现有的仓库导出为一个裸仓库(一个不含当前工作目录的仓库)这通常是很简单的。
1 | git clone --bare myRepository myRepository.git |
现在,你的 myRepository 目录应该有 Git 目录的副本了。
也可以用 cp 来实现:
1 | cp -Rf myRepository/.git myRepository.git |
2、把裸仓库放到服务器上(SSH)
既然已经拥有了裸仓库的副本,剩下要做的就是把裸仓库放到服务器上并设置你的协议。
如果你有一台所有开发者都可以用 SSH 连接的服务器,架设你的第一个仓库就十分简单了, 因为你几乎什么都不用做(正如我们上一节所说的)。 如果你想在你的仓库上设置更复杂的访问控制权限,只要使用服务器操作系统的普通的文件系统权限就行了。
如果需要团队里的每个人都对仓库有写权限,又不能给每个人在服务器上建立账户,那么提供 SSH 连接就是唯一的选择了。 我们假设用来共享仓库的服务器已经安装了 SSH 服务,而且你通过它访问服务器。
这里提供一种方法:在一个主机上建立一个 git 账户,让每一个需要写权限的人发送一个 SSH 公钥,然后将其加入 git 账户的 ~/.ssh/authorized_keys
文件。这样一来,所有人都将通过 git 账户访问主机。这一点也不会影响提交的数据——访问主机用的身份影响提交对象的提交者信息。
3、服务器上的 Git —— 生成 SSH 公钥
目前,许多的 Git 服务器都使用 SSH 公钥进行认证。为了向 Git 服务器提供 SSH 公钥,如果某系统用户为拥有密钥,必须事先为他生成一份。
首先,需要确认一下自己是否已经拥有密钥。默认情况下,用户的 SSH 的密钥存储在其 ~/.ssh
目录下。可以查阅该目录查看是否已经有密钥:
1 | cd ~/.ssh |
我们需要找到一对以 id_dsa
或 id_rsa
命名的文件,其中一个带有 .pub
拓展名,这个就是我们需要用 公钥 (pub = public)如果很可惜并没有找到这个文件也没有关系,可以使用 ssh-keygen
重新创建它。
Linux / MacOS:SSH 软件包
Windows:MSysGit 软件包
使用 ssh-keygen
会确认密钥存储位置(默认为 .ssh/id_rsa)然后回要求你输入两次密钥口令(这里不想填可以直接回车)
然后用户只需要把密钥发给任意一个 Git 服务器管理员。他们需要做的就是复制各自的 .pub 文件内容。
4、服务器上的 Git —— 配置服务器
生成 SSH 公钥后,我们还需要配置服务器的 SSH 访问。其中,我们将使用 authorized_keys
方法对用户进行认证。
我们以 Ubuntu 为例,首先创建一个操作系统用户 git
并用 ssh-keygen
生成一个 .ssh
目录。
我们采用智能化操作 ssh-copy-id
自动完成。
1 | ssh-copy-id [-i [identy_file]] [user@]machine |
六、补充:Ubuntu 使用 ssh 连接远程电脑
Unbuntu 是默认安装了 ssh 的客户端,即可以连接别人的电脑。
ssh 分为服务端和客户端,安装命令:
1 | sudo apt-get install openssh-client # Client |
安装完成后就会自动开启服务,可以通过 ps -e | grep ssh
来查看,如果出现了 ssh-agent
则说明开启成功。
1 | 如果你想要关闭,输入: |
1、连接远程电脑
ssh user@ip
user :该电脑的一个用户
ip: 指该电脑的 ip 地址(远程连接的电脑最好是静态 ip)
如果不知道自己的 ip 地址,可以输入命令查看:
1 | ifconfig |
然后执行命令 ssh user@ip
,执行命令后会让你输入密码,主要输入 user
的密码就行了。
作为首次连接,作为 Server 的一端会询问,联机的 key 尚未建立,是否接受 Server 传来的 Key,并建立联机?
这个时候请务必输入 yes 而不是 y or Y,这样程序才会接受。
2、利用公钥来登陆远程电脑 / 服务器
1 | ssh-copy-id user@machine |
3、补充1: SSH 公钥私钥的原理
其实在我们使用命令 ssh-kegen
的时候,不仅仅生成了一个 id_rsa 而且还有一个 id_rsa.pub 。其中没有后缀的是私钥,是需要保存在本机的(为了系统安全请勿传播私钥),后者为公钥,可以发送给服务器的。
当采用 ssh 远程登录的时候:
- 1)首先客户机请求远程主机,远程主机根据
authorized_keys
中对本机公钥内容加密一个请求,返回给客户端。 - 2)客户端利用私钥解密,然后再发送给远程主机,远程主机收到了准确的应答,就认可了该用户是可信的。因此允许登陆。
所以到头来,最关键的还是公钥与私钥的匹配。所以还是要保护好自己的私钥以免产生安全隐患。
参考网站: CSDN博客
4、补充2:关于电脑通过网络连接的 IP
在进行网络连接的时候,大多数时间我都是访问诸如 www.baidu.com ,www.google.com , www.4399.com 等这一类网站。这些 www.xxx.com (或者是其他 .org , .cn , .us……)这些名字成为 域名(wiki链接),域名简单来说就是一个 IP 地址的别称,主要是可自定义,方便记忆。那么抛开这个别称,我们在网上冲浪的时候,其实电脑连接的是这些别名对应的 IP地址。而像上面提到的我们随时可以访问的 IP地址 其实叫做 公网IP
公网IP :意味着这个是公共的,开放的 IP 地址,我们只要连接互联网均可以访问
与之相对的是 内网IP ,所谓 内网IP 的概念是相对于 公网IP 的,这就需要参考互联网的组成,这里给出一个简单的解释(如果还是不懂可以自行百度一下):
所谓互联网通信,其实本质上是一方(手机、电脑等)连接另一方(一般是服务器,也可以是电脑,智能家居等设备),那么在错综复杂的网络线路中,我们需要将我们的数据传输给对应的接收方。这个听起来有点复杂,其实我们只需要理解成如何把一个快递送到指定的人手中。我们都体验过邮寄服务,当我们需要邮寄给一个人时,我们需要知道 他的地址,在网络世界中, 这个 地址 就是 IP。IP地址也就4个三位数组成,但是我们拥有数以亿计的设备需要在互联网上用心,那么我们该如何给每一个设备都规定一个地址呢?这里就要引入 公网IP 和 内网IP。
那么如何理解 公网IP 和 内网IP 呢?
我们可以假设你邮寄的对方住在 南京市仙林大道123号阳光小区999号,这是一个完整的地址,其中 999号 是对方在小区中的相对门牌号,这个门牌号放在 不同的小区 对应 不同的人 。只有在 阳光小区 才是你需要邮寄的人,因此这个 999号 实际上就是 内网IP,是我们这个 阳光小区内网的一个地址 。而外部的邮递员只需要把邮件发送给阳光小区,拜托阳光小区的业务人员把快递放到家门口。对于邮递员而言,他把包裹发送到阳光小区即可,这时阳光小区对传输而言就是一个公共的,开放的 公网IP 。
如果我们把这种关系用图画出来,应该是一个树状图,每一个节点都是一个 交换机 或者 路由器 ,而每条线路的起点终点都是一台真实存在的设备。通过公网IP找到对应的「小区」,在通过小区找到对应的「门牌号」,就是整个数据传输的过程。网络线路中的邮递员可没有我们真实的邮递聪明,它只认得「小区」这个公网IP,对于内部的「门牌号」内网IP是不可见的。
比如你的路由器给你分配的 IP 地址是 192.168.xxx.xxx。而对于上一级网络这个路由器的 IP 地址是 172.123.123.001 。这个时候有一个服务器 172.123.123.002 只能访问到 172.123.123.001,对于里面的设备是不可以直接访问的,只能拜托路由器把数据转发给 192.168.xxx.xxx 这个内部地址。而对于 192.168.xxx.xxx 他可以拜托路由器把数据发送给 172.123.123.002 。所以如果你是 172.123.123.003 且在这个网络下已经有许多路由器,你想要直接访问 192.168.xxx.xxx ,那么每个路由器会陷入思考——究竟是不是自己的小区的门牌号。这时这个包裹就会被退回,因为你所写的地址不够准确。
显然,公网IP 的个数是有限制的,因此绝大部分我们得到的IP都是内网IP(这个是广义的内网)。但是随着我们
冷知识: 校园网本身就是一个非常巨大的局域网。
参考资料:互联网组成 , 为什么要使用IPV6