GIT

一、理论基础

本地仓库有 Git 维护的三棵“树 工作区域、暂存区域和 Git 仓库

三棵树

工作区域(Working Directory就是你平时存放项目代码的地方。

暂存区域(Stage用于临时存放你的改动,事实上它只是一个文件,保存即将提交的文件列表信息。

Git 仓库(Repository就是安全存放数据的位置,这里边有你提交的所有版本的数据。其中,HEAD 指向最新放入仓库的版本(这第三棵树,确切的说,应该是 Git 仓库中 HEAD 指向的版本)。

Git 的工作流程一般是:

  1. 在工作目录中添加、修改文件;
  2. 将需要进行版本管理的文件放入暂存区域;
  3. 将暂存区域的文件提交到 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
2
3
4
5
git log 
git reflog #常用
git log --graph #图形显示,更直观
git log --pretty=oneline #漂亮一行显示
git log --oneline #简洁显示

三、 回退–reset

有关回退的命令有两个:reset 和 checkout,具体功能如下图:

image-20200805143304099

先看reset :

操作之前的仓库状态:

image-20200805145833346

此时三棵树:

image-20200805145904018

现在我们利用 reset 命令回滚快照(快照即提交的版本,每个版本我们称之为一个快照。),并看看 Git 仓库和三棵树分别发生了什么。

执行 git reset HEAD~ 命令:

注:HEAD 表示最新提交的快照,而 HEAD~ 表示 HEAD 的上一个快照,HEAD~~表示上上个快照,如果表示上n个快照,则可以用HEAD ~n

此时我们的快找回滚到了第二棵数(暂存区域)

image-20200805150102706

image-20200805150127577

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
2
3
4
git config --global i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8
export LESSCHARSET=utf-8 ## linux bash配置环境变量
set LESSCHARSET=utf-8 #windows配置环境变量

image-20200805155547724

含义:
第一行: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
2
git diff --cached
git diff --cached 快照ID

5、总结

image-20200805164135352

五、修改最后一次提交、删除文件和重命名文件

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
2
git checkout 分支名
git checkout -b 分支名   #创建分支并切换到该分支

PS:执行 git log --oneline --decorate --graph --all 命令: 绘制所有分支图并显示。

3、合并分支

1
2
git merge xxx
#注:要将xxx分支合并到master,就先切换到master,然后执行上述命令

冲突问题:

所谓冲突,无非就是像两个分支中存在同名但内容却不同的文件,Git 不知道你要舍弃哪一个或保留哪一个,所以需要你自己来决定。此时执行 git status 命令也会显示需要你解决的冲突。解决:打开冲突文件,Git 会在有冲突的文件中加入一些标记,以=======为界,上到<<<<<<< HEAD 的内容表示当前分支,下到>>>>>>> 分支名表示待合并的分支,之间的内容就是冲突的地方,删除特殊符号,文件内容改成需要的即可。

4、删除分支

1
git branch -d 分支名

七、checkout(&reset)

1、再论checkout

事实上,checkout 命令有两种功能:

  • 从历史快照(或者暂存区域)中拷贝文件到工作目录
  • 切换分支

1)从历史快照(或者暂存区域)中拷贝文件到工作目录

1
2
git checkout HEAD~ README.md  #将上一个快照中的 README.md 文件复制到工作目录和暂存区域中
git checkout README.md #从暂存区域恢复指定文件到工作目录

2)切换分支

1
2
git checkout 分支名
# 将HEAD指针切换到指定分支(并将上一个快照中的文件复制到工作目录和暂存区域中

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
3
4

git remote -v #查看远程地址别名
git remote add 别名 远程地址
#例:git remote add origin https://xx

2、 推送

1
2
3
git push 别名 分支名
git push -u 别名 分支名 #-u指定默认主机
#例:git push origin master

3、clone

1
git clone  https://xx

效果:

  • 完整的把远程库下载到本地
  • 创建origin远程地址别名
  • 初始化本地库

4、pull(=fetch+merge)

1
2
3
git fetch 别名 分支名  #只是把远程内容下下载到本地,不会修改本地工作区文件
git merge 别名 分支名 #合并
git pull 别名 分支名 #pull=fetch+merge

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 后缀的文件。

Author: Krab
Link: https://isxrh.github.io/2020/08/05/202008_GIT/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.