一.基本操作
1.创建本地仓库
在对应文件目录下进行:
bash
git init
输入完上面的代码,所在文件目录下就会多一个名为 .git 的隐藏文件,该文件是Git用来跟踪和管理仓库的。
我们可以使用 tree 命令(注意要先下载tree插件)来查看 .git 文件的细节:

创建完后我们一定要配置配置Git,设置用户名和邮箱地址:
bash
git config [--global] user.name "***"
git config [--global] user.email "***"
global是一个选择选择项,填上这个表示这台机器上所有的Git仓库都会使用这个用户名和邮箱地址。
能设置自然也能删除配置:
bash
git config [--global] --unset user.name
git config [--global] --unset user.email
了解完配置与删除,我们可以使用下面的命令来查看配置:
bash
git config -l

2.工作区、暂存区、版本库(重要)

工作区:我们在本地的目录;
暂存区(stage、index):一般存放在 .git 目录下的index文件;
版本库:隐藏目录 .git 。
我们在本地,也就是工作区创建的文件,可以通过add操作将文件上传到暂存区;我们可以使用commit命令将暂存区的文件上传到版本库中。从这里也可以看出,我们新创建的文件没有经过add和commit命令是没有添加到仓库中的。
bash
//指定文件名,可写多个,用空格隔开
git add 文件名
//所有文件
git add .
通过这里的学习也解开了我之前的疑惑,那就是我在提交文件名有空格的文件时一直报错,原来用了空格表示不是一个文件了。如果真有空格,可以使用引号括起来;也可以使用 \ 来转义空格。
bash
git commit -m "信息"
//指定文件到版本库中
git commit 文件名 -m "信息"
这里是信息指的是本次提交的细节。
通过上面两个步骤我们就将代码提交到版本库里了。我们可以使用下面的命令来查看历史提交记录:
bash
git log [--pretty=oneline]
--pretty=oneline 是一个可选项,加上这个会使历史提交记录显示的更加简洁。
通过上面的命令我们会得到下面的内容:
bash
4e65c55222473e05e72338d3ba75a101a6a56d56 First commit
前面这一堆数字和字母是commit id,这个很重要,下面会说到。
在使用上面的 tree .git 命令查看,我们可以看到objects中存入了commit id。

在最上面的那张图上我们可以看到head指向master,我们查看以下master的内容,发现:
bash
4e65c55222473e05e72338d3ba75a101a6a56d56
其中存着的正是上面的commit id。这个master存的正是最新的commit id。
下面着重说一下objects。
对一开始那张图进行补充:

objects 为Git的对象库,里面包含了创建的各种版本库对象及内容。
我们使用:ls .git/objects/ 来查看objects中的文件:
bash
4e 70 e6 info pack

为什么是这个,其实从树上就能得到答案。
我们可以通过:git cat-file 命令来查看版本库中的内容:

输入下面的命令:
bash
git cat-file -p 4e65c55222473e05e72338d3ba75a101a6a56d56
我们得到了:
bash
tree 70ea63592ac4de5f9aec6b15273c4dd5cc0cd00f
3.修改文件
查看在上次提交之后是否有对文件进行再次修改:
bash
git status
查看工作区文件与暂存区或版本库文件的差异:
bash
//工作区与暂存区差异
git diff [文件]
//工作区与版本库差异
git diff HEAD -- [文件]
4.版本回退
git reset 命令用于回退版本,其后面还有几个可选项:
bash
git reset [--soft | --mixed | --hard] [HEAD]
|-----|-------------|-------------|-------------|---------|
| | 工作区 | 暂存区 | 版本库 | 选项 |
| 原本 | file1、file2 | file1、file2 | file1、file2 | |
| 回退后 | file1、file2 | file1、file2 | file1 | --soft |
| 回退后 | file1、file2 | file1 | file1 | --mixed |
| 回退后 | file1 | file1 | file1 | --hard |
其中 --mixed是默认选项。
上面表格不难理解,举个例子如果我们使用了**--soft**,那么只有版本库回退了,工作区和暂存区都没有回退。
HEAD选项:
|-----------|----------|
| commit id | 回退到指定版本 |
| HEAD | 表示当前版本 |
| HEAD^ | 表示上一个版本 |
| HEAD~1 | 表示上一个版本 |
| HEAD~2 | 表示上上一个版本 |
5.删除文件
删除工作区和暂存区的文件:
git rm 文件名
二.分支管理
1.分支是什么
每次commit,git会根据时间形成一条"时间线",这条时间线就是分支。git里面有一条主分支,master分支。HEAD指向master。

2.基本操作
1)查看分支
bash
git branch
2)创建分支
bash
git branch 分支名
比如我们创建一个dev分支:

此时再查看分支:

3)切换分支
bash
git checkout 分支名
切换完后,HEAD就会指向切换的分支,比如我们切换到了dev分支:
如果这个时候我们修改了某个文件,并且add和commit了,那么就会变成这样:

如果此时我们切回master,打开刚刚修改文件,我们就会发现文件没有被修改。原因从图上也能看出,master跟dev指向的根本就不是一个东西。修改的只是dev分支的文件,master分支没有被修改。
4)合并分支
像刚刚上面的例子,只有dev分支文件被修改了,我们想要将这个修改合并到master分支。
第一步,我们要先切换到master分支。
第二步,合并:
bash
git merge dev
5)删除分支
bash
git branch -d 分支名
这里要注意,我们要删除某一个分支,HEAD一定不能指向这个分支,如果指向这个分支是删不了的。
还有,如果这个分支的没有被合并,这个时候使用上面的方法是删不掉分支的,我们要这样写强制删除分支:
bash
git branch -D 分支名
3.合并冲突
我们在dev分支修个了file1文件,同时也在master分支修改了file1文件,如果将这两个分支合并就会发生冲突,git根本就不知道该听谁的,是要dev分支的修改还是master分支的修改。这就是合并冲突。

我们的解决办法也很原始,手动删。
当出现冲突报错后,再打开file1文件就会发现文件内容变成这样了:
<<< ==== >>>这些符号是用来向我们区分不同分支的冲突的。我们只需要留下我们真正需要的内容即可。
修改完后我们要再次add和commit一次,这个一定不能漏。

我们使用下面的命令也可以参看到这个结构:
git log --graph --pretty=oneline --abbrev-commit

4.合并模式
在没有合并冲突的情况下,git会优先使用Fast forward模式。这个模式有一个问题,在我们删除合并完删除分支后,会丢失分支信息,我们无法知道最新的commit是不是合并出来的。
为了解决这个问题,我们要使用普通模式:
git merge --no-ff -m "" 分支名
三.远程操作
前面的操作其实都是在本地操作的,我们在实际开发时,不可能所有人都在一台设备上操作,每个人一台独立的设备,都在自己的设备上进行开发。这个时候就需要一个远程仓库,每个将写的代码提交到远程仓库中,远程仓库可以自己搭建,也可以是使用GitHub或Gitee等。
下面使用Gitee做示范。
1.克隆远程仓库

打开右上角克隆/下载,里面会有:

为什么可以选择使用上面的地址克隆。
这里只以HTTPS和SSH为例。
对于HTTPS,操作很简单,只需要将上面的地址复制:
git clone 地址
2.推送到远程仓库
将远程克隆到本地后,我们可以使用命令将本地仓库的代码推送到远程仓库中:
git push 远程主机名 本地分⽀名:远程分⽀名
# 如果本地分⽀名与远程分⽀名相同,则可以省略冒号
git push 远程主机名 本地分⽀名
比较常见的就是下面这个:
git push origin master
3.拉取远程仓库
如果别人修改了代码并提交到远程仓库,我们要与远程仓库的代码同步,这个时候就要使用拉取操作了:
git pull 远程主机名 本地分⽀名:远程分⽀名
# 如果本地分⽀名与远程分⽀名相同,则可以省略冒号
git pull 远程主机名 本地分⽀名
git pull 命令其实执行了两个操作,一个是从远程仓库拉取代码,一个是与本地分支合并。
4.配置git
1)忽略特殊文件
在我们初始化仓库的时候,我们添加了一个 .gitignore文件:

写入这个文件的文件在使用 **git add .**时就不会一起提交了。
比如我们想忽略所有 .ini 结尾的文件,那么我们就可以写:
*.ini
如果我们在忽略的文件中 a.ini 我们是想让其提交的,这个时候我们可以写:
*.ini
!a.ini
2)命令配置别名
比如我们想给 git status 起一个别名:
git config [--global] alias.st status
此时我们使用 git st 与使用 git status 的效果是一样的。
我们配置完命令后,原来的命令还是可以用的,其与我们的配置是并存的。
四.标签管理
标签tag,可以简单的理解是某次commit的一个标识,相当于起了一个别名。
1.创建标签
先切换到要创建标签的分支,然后创建标签:
git tag 标签名
创建完后我们可以使用 git tag 来查看我们创建的标签,但是要注意标签不是按时间顺序列出,而是按字母排序的。
2.操作标签
删除本地标签:
git tag -d 标签名
删除远程仓库标签:
git push origin :refs/tags/标签名
将本地标签推送到远程仓库:
git push origin 标签名
# 将全部标签推送
git push origin --tags