Git入门到精通

Git概述

Git是一个免费开源的分布式版本控制系统

工作原理

图片

Git和代码托管中心

代码托管中心是基于网络服务器的远程代码仓库——远程库

  • GitLab

  • GitHub

  • Gitee

常用命令

#Bash中"#"代表注释
#在Bash界面按Tab键可以自动补全命令
##########以下是常用Linux命令############
cd 路径 #改变目录
cd .. #回到上级目录
pwd #显示当前所在目录路径
ls #列出当前目录中的所有文件(夹),不过没有ll详细,不包含隐藏文件
ls -a #列出当前目录中的所有文件(夹),不过没有ll详细,包含隐藏文件
ll #查看当前目录下的文件(夹),不包含隐藏文件
ll -a #查看当前目录下的文件(夹),包含隐藏文件
touch 文件名 #新建一个文件,如:touch index.html 就会在当前目录下新建一个index.html文件
rm 文件名 #删除一个文件
mkdir 文件夹名 #新建一个文件夹
rm -f #删除一个文件夹,如:rm -f src 删除src文件夹
#rm -rf /在Linux中是删除电脑中全部文件!
mv 文件名 路径 #移动文件到指定文件夹下,如:rm index.html src 移动index.html到当前目录下的src文件夹下
reset #重新初始化终端,相当于清屏
clear #清屏 快捷键 Ctrl+L
history #查看历史命令
help #查看帮助
exit #脱出
vim 文件名 #使用vim编辑器打开文件进行编辑
cat 文件名 #查看文件内容

##############以下是Bash快捷键##############
#清屏 Ctrl+L
#复制 Ctrl+insert(鼠标左键双击也行)
#粘贴 shift+insert(鼠标中键单击也行)
#切换历史命令 Ctrl+左右方向键

##############以下是vim快捷键##############
#Esc可以退出编辑模式,从而可以使用快捷键
#按两次y是复制
#p是粘贴
#按两次d删除当前行
#:可以输入命令
#wq是保存文件

############以下是常用Git命令##############
git config -l #查看配置
git config --system --list #查看系统级(system)配置,配置文件位于Git安装目录下的etc下的gitconfig
git config --global  --list #查看全局级(global)配置,配置文件位于用户目录下的.gitconfig
git config --global user.name 用户名 #设置用户签名(必要)
git config --global user.email 邮箱 #设置用户签名(必要)

#生产秘钥
ssh-keygen -t rsa -C ""
#-C:C是comment的缩写
#-C表示提供一个注释,用于识别这个密钥。
#“你的邮箱地址(因为邮箱地址具有唯一性所以一般用这个)”:用于识别这个密钥的注释
#引号里的内容为注释的内容,所以" "里面不一定填邮箱,可以输入任何内容。

git init #初始化本地库(将当前目录变成git可以管理的仓库)
git status #查看本地库状态
git add 文件名 #添加到暂存区
git add . #将当前目录文件添加到暂存区里去
git rm --cached 文件名 #把该文件从暂存区移除,但工作区中的该文件还在
git restore --staged 文件名 #同上
git commit -m "日志信息" 文件名 #提交到本地库
git reflog #查看版本日志信息
git log #查看详细版本日志信息
git reset --hard 版本号 #版本穿梭

分支操作

git branch 分支名 #创建分支
git branch -v #查看分支
git checkout 分支名 #切换分支
git checkout -b 分支名 #创建并切换分支
git merge 分支名 #把指定的分支合并到当前分支上

#Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。

git rebase 分支名 #将当前分支继承自指定的分支

#HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。HEAD 通常情况下是指向分支名的(如 bugFix)。在你提交时,改变了 bugFix 的状态,这一变化通过 HEAD 变得可见。分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:
#HEAD -> main -> C1
#HEAD 指向 main, main 指向 C1

git checkout c1

#现在变成了
#HEAD -> C1


相对引用

通过指定提交记录哈希值的方式在 Git 中移动不太方便。在实际应用时,并没有像本程序中这么漂亮的可视化提交树供你参考,所以你就不得不用 git log 来查查看提交记录的哈希值。

并且哈希值在真实的 Git 世界中也会更长(译者注:基于 SHA-1,共 40 位)。例如前一关的介绍中的提交记录的哈希值可能是 fed2da64c0efc5293610bdd892f82a58e8cbc5d8。舌头都快打结了吧...

比较令人欣慰的是,Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2 而不是上面的一长串字符。

正如我前面所说,通过哈希值指定提交记录很不方便,所以 Git 引入了相对引用。这个就很厉害了!

使用相对引用的话,你就可以从一个易于记忆的地方(比如 bugFix 分支或 HEAD)开始计算。

相对引用非常给力,这里我介绍两个简单的用法:

  • 使用 ^ 向上移动 1 个提交记录
  • 使用 ~<num> 向上移动多个提交记录,如 ~3

"^"操作符

把这个符号加在引用名称的后面,表示让 Git 寻找指定提交记录的父提交。

所以 main^ 相当于“main 的父节点”。

main^^main 的第二个父节点

现在咱们切换到 main 的父节点

image-20220622175901211

git checkout main^

搞定。这种方式是不是比输入哈希值方便多了?!

image-20220622175958870

你也可以将 HEAD 作为相对引用的参照。

"~"操作符

如果你想在提交树中向上移动很多步的话,敲那么多 ^ 貌似也挺烦人的,Git 当然也考虑到了这一点,于是又引入了操作符 ~

该操作符后面可以跟一个数字(可选,不跟数字时与 ^ 相同,向上移动一次),指定向上移动多少次。咱们还是通过实际操作看一下吧

咱们用 ~<num> 一次后退四步。

image-20220622180620660

git checkout HEAD~4

多么的简洁 —— 相对引用就是方便啊!

image-20220622180659213

强制修改分支位置

你现在是相对引用的专家了,现在用它来做点实际事情。

image-20220622180847209

使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:

git branch -f main HEAD~3

上面的命令会将 main 分支强制指向 HEAD 的第 3 级父提交

现在咱们来演示一下上面的命令

image-20220622180933059

这就对了! 相对引用为我们提供了一种简洁的引用提交记录 C1 的方式, 而 -f 则容许我们将分支强制移动到那个位置。

撤销变更

在 Git 里撤销变更的方法很多。和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。我们这个应用主要关注的是后者。

主要有两种方法用来撤销变更 —— 一是 git reset,还有就是 git revert。接下来咱们逐个进行讲解。

git reset

git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。

让我们来看看演示:

image-20220622190838456

git reset HEAD~1

漂亮! Git 把 main 分支移回到 C1;现在我们的本地代码库根本就不知道有 C2 这个提交了。

image-20220622190937253

git revert

虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的哦!

为了撤销更改并分享给别人,我们需要使用 git revert。来看演示:

image-20220622190838456

git revert HEAD

image-20220622191247164

奇怪!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录 C2' 引入了更改 —— 这些更改刚好是用来撤销 C2 这个提交的。也就是说 C2' 的状态与 C1 是相同的。

revert 之后就可以把你的更改推送到远程仓库与别人分享啦。

远程仓库

远程仓库并不复杂, 在如今的云计算盛行的世界很容易把远程仓库想象成一个富有魔力的东西, 但实际上它们只是你的仓库在另个一台计算机上的拷贝。你可以通过因特网与这台计算机通信 —— 也就是增加或是获取提交记录

话虽如此, 远程仓库却有一系列强大的特性

  • 首先也是最重要的的点, 远程仓库是一个强大的备份。本地仓库也有恢复文件到指定版本的能力, 但所有的信息都是保存在本地的。有了远程仓库以后,即使丢失了本地所有数据, 你仍可以通过远程仓库拿回你丢失的数据。
  • 还有就是, 远程让代码社交化了! 既然你的项目被托管到别的地方了, 你的朋友可以更容易地为你的项目做贡献(或者拉取最新的变更)

现在用网站来对远程仓库进行可视化操作变得越发流行了(像 GitHub), 但远程仓库永远是这些工具的顶梁柱, 因此理解其概念非常的重要!

git fetch

Git 远程仓库相当的操作实际可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据。既然我们能与远程仓库同步,那么就可以分享任何能被 Git 管理的更新(因此可以分享代码、文件、想法、情书等等)。

本节课我们将学习如何从远程仓库获取数据 —— 命令如其名,它就是 git fetch

你会看到当我们从远程仓库获取数据时, 远程分支也会更新以反映最新的远程仓库。

image-20220622201319890

git fetch

image-20220622201345587

就是这样了! C2,C3 被下载到了本地仓库,同时远程分支 o/main 也被更新,反映到了这一变化