一、理论基础
本地仓库有 Git 维护的三棵“树 工作区域、暂存区域和 Git 仓库
工作区域(Working Directory就是你平时存放项目代码的地方。
暂存区域(Stage用于临时存放你的改动,事实上它只是一个文件,保存即将提交的文件列表信息。
Git 仓库(Repository就是安全存放数据的位置,这里边有你提交的所有版本的数据。其中,HEAD 指向最新放入仓库的版本(这第三棵树,确切的说,应该是 Git 仓库中 HEAD 指向的版本)。
Git 的工作流程一般是:
- 在工作目录中添加、修改文件;
- 将需要进行版本管理的文件放入暂存区域;
- 将暂存区域的文件提交到 Git 仓库。
因此,Git 管理的文件有三种状态:已修改(modified)、**已暂存(staged)**和 已提交(committed),依次对应上面的每一个流程。
二、基本操作
1、初始化git项目
1 | git init |
2、将工作区的文件加入暂存区域:
1 | git add 文件名 |
3、将暂存区内容提交到本地库:
1 | git commit -m "你干了啥" |
4、将工作区的文件放到Git仓库(一步到位):
1 | git commit -am "你干了啥" |
5、查看状态:
1 | git status |
6、查看历史操作记录:
1 | git log |
三、 回退–reset
有关回退的命令有两个:reset 和 checkout,具体功能如下图:
先看reset :
操作之前的仓库状态:
此时三棵树:
现在我们利用 reset 命令回滚快照(快照即提交的版本,每个版本我们称之为一个快照。),并看看 Git 仓库和三棵树分别发生了什么。
执行 git reset HEAD~
命令:
注:HEAD 表示最新提交的快照,而 HEAD~ 表示 HEAD 的上一个快照,HEAD~~表示上上个快照,如果表示上n个快照,则可以用HEAD ~n
此时我们的快找回滚到了第二棵数(暂存区域)
1、reset命令的选项:
1 | git reset --soft HEAD~ |
- 移动HEAD的指向,将其指向上一个快照
(只移动 HEAD 的指向,但并不会将快照回滚到暂存区域。相当于撤消了上一次的提交(commit))
1 | git reset [--mixed] HEAD~ |
- 移动HEAD的指向,将其指向上一个快照
- 将HEAD移动后指向的快照回滚到暂存区域
1 | git reset --hard HEAD~ |
- 移动HEAD的指向,将其指向上一个快照
- 将HEAD移动后指向的快照回滚到暂存区域
- 将暂存区域的文件还原到工作目录
2、回滚指定快照
reset 不仅可以回滚指定快照,还可以回滚个别文件。
命令格式为: git reset 快照 文件名/路径
这样,它就会将忽略移动 HEAD 的指向这一步(因为你只是回滚快照的部分内容,并不是整个快照,所以 HEAD 的指向不应该发生改变),直接将指定快照的指定文件回滚到暂存区域。
3、往前滚
即滚向未来,需要知道指定快照的 ID 号。
不小心把命令窗口关了不记得ID号?
命令:git reflog
Git记录的每一次操作的版本ID号
四、版本对比
1、比较暂存区域与工作目录的文件内容
1 | git diff |
(PS:解决cmd界面中文乱码👇
1 | git config --global i18n.commitencoding utf-8 |
含义:
第一行:diff --git a/README.md b/README.md
表示对比的是存放在暂存区域的 README.md
和工作目录的 README.md
第二行:index 7966837..472a180 100644
表示对应文件的 ID 分别是 7966837 和 472a180,左边暂存区域,后边当前目录。最后的 100644 是指定文件的类型和权限。
第三行:--- a/README.md
— 表示该文件是旧文件(存放在暂存区域)
第四行:+++ b/README.md
+++ 表示该文件是新文件(存放在工作区域)
第五行:@@ -1 +1,2 @@
以 @@ 开头和结束,中间的“-”表示旧文件,“+”表示新文件,后边的数字表示“开始行号,显示行数”
第六、七行:
这是将两个文件合并显示的结果,前边有个 + 的绿色行是新文件独有的,浅灰色的则是两个文件所共有的内容。(旧文件没有自己“独有的”内容会以 前边有个 - 号的 红色字体显示)。
第八行:\ No newline at end of file
文件不是以换行符结束
最后的(:)
意思是窗口太小,没办法显示全部,正在等待命令(Vim编程知识)
移动命令
j、k
:向下移动一行/向上移动一行f、b
:向下翻页/向上翻页d、u
:向下翻半页/向上翻半页
跳转命令g、G
:跳转到第一行/跳转到最后一行n g
,表示跳转到第 n 行
搜索命令/ 关键字
: 表示从当前位置向下搜索
?关键字
: 表示从当前位置向上搜索。
接着输入 n 表示顺着当前的搜索方向快速跳转到下个匹配的位置,大写的 N 则是与当前搜索方向相反。
退出q
: 表示退出 diff帮助
h
:表示进入帮助界面,输入 q 可以退出帮助界面。
2、比较两个历史快照
1 | git diff 快照ID 快照ID |
3、比较当前工作目录和 Git 仓库中的快照
1)比较之前版本的快照与当前工作目录内容
1 | git diff 快照ID |
2)比较当前版本快照与当前工作目录内容
1 | git diff HEAD |
4、比较Git仓库与暂存区域
1 | git diff --cached |
5、总结
五、修改最后一次提交、删除文件和重命名文件
1、修改最后一次提交
1 | git commit -amend |
进入“编辑提交说明界面”,连续按下两个大写Z来退出,或者按下(:)再输入q!退出。
1 | git commit --ammend -m “新的提交说明” |
直接提交说明。
2、删除文件
1)恢复不小心删除的文件
1 | git checkout -- README.md |
2)彻底删除一个文件
1 | git rm 文件名 |
但是,此时执行git status
会发现操作记录,若想删除记录,可以执行 git reset --soft HEAD~
命令将快照回滚到上一个位置,然后重新提交
3)暂存区域和工作目录文件不同时(add之后又进行了修改)
1 | git rm -f 文件名 |
全部删除
3、重命名文件
1 | git mv 旧文件名 新文件名 |
六、Git分支
1、创建分支
1 | git branch 分支名 |
通过git log --decorate
命令(git log --decorate --oneline
只用一行来显示一个快照记录)查看记录,可以看到最新的快照后边多了一个 (HEAD -> master, 分支名)
,表示:目前有两个分支,一个是主分支(master),一个是刚才我们创建的新分支, HEAD 指针仍然指向默认的 master 分支。
2、切换分支
1 | git checkout 分支名 |
PS:执行 git log --oneline --decorate --graph --all
命令: 绘制所有分支图并显示。
3、合并分支
1 | git merge xxx |
冲突问题:
所谓冲突,无非就是像两个分支中存在同名但内容却不同的文件,Git 不知道你要舍弃哪一个或保留哪一个,所以需要你自己来决定。此时执行 git status 命令也会显示需要你解决的冲突。解决:打开冲突文件,Git 会在有冲突的文件中加入一些标记,以=======
为界,上到<<<<<<< HEAD
的内容表示当前分支,下到>>>>>>> 分支名
表示待合并的分支,之间的内容就是冲突的地方,删除特殊符号,文件内容改成需要的即可。
4、删除分支
1 | git branch -d 分支名 |
七、checkout(&reset)
1、再论checkout
事实上,checkout 命令有两种功能:
- 从历史快照(或者暂存区域)中拷贝文件到工作目录
- 切换分支
1)从历史快照(或者暂存区域)中拷贝文件到工作目录
1 | git checkout HEAD~ README.md #将上一个快照中的 README.md 文件复制到工作目录和暂存区域中 |
2)切换分支
1 | git checkout 分支名 |
2、checkout 与reset区别
1)恢复文件
checkout 命令和 reset 命令都可以用于恢复指定快照的指定文件,并且它们都不会改变 HEAD 指针的指向。
区别:reset 命令只将指定文件恢复到暂存区域(–mixed),而 checkout 命令是同时覆盖暂存区域和工作目录。
注意:也许你试图使用 git reset –hard HEAD~ README.md 命令让 reset 同时覆盖工作目录,但 Git 会告诉你这是徒劳(此时 reset 不允许使用 –soft 或 –hard 选项)。
这样看来,在恢复文件方面,reset 命令要比 checkout 命令更安全一些。
2)恢复快照
reset 命令是用来”回到过去”的,根据选项的不同,reset 命令将移动 HEAD 指针(–soft) -> 覆盖暂存区域(–mixed,默认)-> 覆盖工作目录(–hard)。
checkout 命令虽说是用于切换分支,但它事实上也是通过移动 HEAD 指针和覆盖暂存区域、工作目录来实现的。
区别:
- 对于 reset –hard 命令来说,checkout 命令更安全。因为 checkout 命令在切换分支前会先检查一下当前的工作状态,如果不是“clean”的话,Git 不会允许你这样做;而 reset –hard 命令则是直接覆盖所有数据。
- 另一个区别是如何更新 HEAD 指向,reset 命令会移动 HEAD 所在分支的指向,而 checkout 命令只会移动 HEAD 自身来指向另一个分支。
八、Git&Github
1、创建远程库地址别名
1 |
|
2、 推送
1 | git push 别名 分支名 |
3、clone
1 | git clone https://xx |
效果:
- 完整的把远程库下载到本地
- 创建origin远程地址别名
- 初始化本地库
4、pull(=fetch+merge)
1 | git fetch 别名 分支名 #只是把远程内容下下载到本地,不会修改本地工作区文件 |
5、解决冲突
如果不是基于远程库最新版做的修改不能推送,必须先pull下来,pull下来如果进入冲突状态,按照”分支冲突解决”操作解决即可。
6、SSH
- 输入:
ssh-keygen -t rsa -C GitHub邮箱地址
- 进入
.ssh
目录,复制id_rsa.pub
文件内容 - 登录GitHub。
Settings
–>SSH and GPG keys
–>New SSH Key
- 回到git通过ssh地址创建。
git remote add 别名 SSH地址
Tips:
如何让Git 识别某些格式的文件,然后自主不跟踪它们?
比如工作目录中有三个文件1.temp、2.temp 和 3.temp,我们不希望后缀名为 temp 的文件被追踪。
Solution:在工作目录创建一个名为 .gitignore 的文件。
注:windows需要在命令行窗口创建(.)开头的文件。
执行 echo *.temp > .gitignore
命令,创建一个 .gitignore 文件,并让 Git 忽略所有 .temp 后缀的文件。