## git学习
### git 简介
Git是什么?
Git是目前世界上最先进的分布式版本控制系统(没有之一)。
### git for windows的安装
#### 一些选项
<!-- more -->
![git安装1](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E5%AE%89%E8%A3%851.png)
git GUI 和 git Bash
![gitGui和Bash](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/gitGUI%E5%92%8CgitBash.png)
#### 选择默认的编辑器
![git安装2(编辑器选择)](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E5%AE%89%E8%A3%852%28%E7%BC%96%E8%BE%91%E5%99%A8%E9%80%89%E6%8B%A9%29.png)
#### 三个选择
选项一,不会修改系统环境变量,但是Windows系统cmd命令行中无法使用git命令
选项二,会将git相关程序加入系统环境变量中,使得Windows系统cmd命令行中可以使用git命令
选项三,会将git相关程序以及一些其他的Unix工具加入系统环境变量,使得Windows系统cmd命令行中可以使用git以及Unix工具。要注意的是,这将覆盖Windows工具,如 “ find 和 sort ”。只有在了解其含义后才使用此选项。
![git安装3(git使用方式和环境变量)](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E5%AE%89%E8%A3%853%28git%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F%29.png)
#### 选择库
选项一,使用 OpenSSL 库
选项二,使用本地 Windows 安全通道库
![git安装4(是否使用openssl)](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E5%AE%89%E8%A3%854%28%E6%98%AF%E5%90%A6%E4%BD%BF%E7%94%A8OpenSSl%29.png)
#### 换行符转换的三个选择
选项一,选项让Git能够自动转换文件中的换行符;签出到本地时转换为Windows下的换行符,提交到服务器时转换为Unix下的换行符
选项二,选项让Git在签出到本地时不做转换,保留原始文件的换行符;提交到服务器时转换为Unix下的换行符
选项三,让Git在签出到本地时和提交到服务器时都不做转换
![git安装5(换行符格式)](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E5%AE%89%E8%A3%855%28%E6%8D%A2%E8%A1%8C%E7%AC%A6%E7%9A%84%E6%A0%BC%E5%BC%8F%29.png)
#### 是否选择MinTTy作为终端模拟器
选项一,Git Bash将使用MinTTY作为终端模拟器,该模拟器具有可调整大小的窗口,非矩形选区和Unicode字体
选项二,选项使用Windows系统cmd命令行来作为Git命令行
#### git pull的默认作用
默认值是快进或者合并
![git安装6](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git学习/git安装6(git pull的作用).png)
#### git安装的额外选项
![git安装7(额外选项)](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E5%AE%89%E8%A3%857%28%E9%A2%9D%E5%A4%96%E9%80%89%E9%A1%B9%29.png)
### git的安装后配置
#### 如果windows在cmd中输入git命令回车之后说明你的git安装成功了
![git安装成功证明图片](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E5%AE%89%E8%A3%85%E6%88%90%E5%8A%9F%E5%9B%BE%E7%89%87.png)
#### 配置名字和邮箱地址
> --global 参数是指你这台机器上所有的Git仓库都会使用这个配置
```shell
git config --global user.name "你的名字"
git config --global user.email "email@example.com"
```
#### git配置文件的存放地址
在 Windows 系统中,Git 会查找 `$HOME` 目录下(一般情况下是 `C:\Users\$USER` )的 `.gitconfig` 文件。
你可以通过以下命令来查看所有的配置以及它们所在的文件:
> git config --list --show-origin
```powershell
> git config --list --show-origin
file:D:/EnglishSoftware/Git/etc/gitconfig diff.astextplain.textconv=astextplain
file:D:/EnglishSoftware/Git/etc/gitconfig filter.lfs.clean=git-lfs clean -- %f
file:D:/EnglishSoftware/Git/etc/gitconfig filter.lfs.smudge=git-lfs smudge -- %f
file:D:/EnglishSoftware/Git/etc/gitconfig filter.lfs.process=git-lfs filter-process
file:D:/EnglishSoftware/Git/etc/gitconfig filter.lfs.required=true
file:D:/EnglishSoftware/Git/etc/gitconfig http.sslbackend=openssl
file:D:/EnglishSoftware/Git/etc/gitconfig http.sslcainfo=D:/EnglishSoftware/Git/mingw64/ssl/certs/ca-bundle.crt
file:D:/EnglishSoftware/Git/etc/gitconfig core.autocrlf=true
file:D:/EnglishSoftware/Git/etc/gitconfig core.fscache=true
file:D:/EnglishSoftware/Git/etc/gitconfig core.symlinks=false
file:D:/EnglishSoftware/Git/etc/gitconfig core.editor="D:\\EnglishSoftware\\notepad++\\notepad++.exe" -multiInst -notabbar -nosession -noPlugin
file:D:/EnglishSoftware/Git/etc/gitconfig pull.rebase=false
file:D:/EnglishSoftware/Git/etc/gitconfig credential.helper=manager
file:C:/Users/abc/.gitconfig user.name=你的名字
file:C:/Users/abc/.gitconfig user.email=你的邮箱
file:.git/config core.repositoryformatversion=0
file:.git/config core.filemode=false
file:.git/config core.bare=false
file:.git/config core.logallrefupdates=true
file:.git/config core.symlinks=false
file:.git/config core.ignorecase=true
file:.git/config gui.wmstate=normal
file:.git/config gui.geometry=1061x563+32+32 233 255
```
如果想要检查你的配置,可以使用 `git config --list` 命令来列出所有 Git 当时能找到的配置。
它包括系统自己的配置文件信息 和 你设定的配置信息
```powershell
$ git config --list
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=D:/EnglishSoftware/Git/mingw64/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=false
core.editor="D:\\EnglishSoftware\\notepad++\\notepad++.exe" -multiInst -notabbar -nosession -noPlugin
pull.rebase=false
credential.helper=manager
user.name=你的名字
user.email=你的邮箱
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
gui.wmstate=normal
gui.geometry=1061x563+32+32 233 255
```
使用 `git config --global --list` 可以列出用户配置
这个文件windows一般是`C:\Users\$USER`的`.gitconfig`文件
```shell
> git config --global --list
user.name=你的名字
user.email=你的邮箱
```
使用git config --system --list 可以列出系统配置
这个配置文件是 git安装目录下的 `etc/gitconfig `文件
```shell
> git config --system --list
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=D:/EnglishSoftware/Git/mingw64/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=false
core.editor="D:\\EnglishSoftware\\notepad++\\notepad++.exe" -multiInst -notabbar -nosession -noPlugin
pull.rebase=false
credential.helper=manager
```
### git的基本特点(核心原理)
#### 利用hash值来计算
Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成,看起来就像是:
24b9da6552252987aa493b52f8696cd6d3b00373
Git 的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。
#### git记录修改
为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是`修改`,而非文件。
你会问,什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。
以下是git的存储更迭示意图
虚线表示没变 实线表示内容有修改
![git版本更新图示](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/git%E7%89%88%E6%9C%AC%E6%9B%B4%E6%96%B0%E5%9B%BE%E7%A4%BA.png)
#### 文件的三种状态
对于任何一个文件,在 Git 内都只有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。
由此我们看到 Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。
![工作区、暂存区以及 Git 目录](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/%E5%B7%A5%E4%BD%9C%E5%8C%BA%E3%80%81%E6%9A%82%E5%AD%98%E5%8C%BA%E4%BB%A5%E5%8F%8A%20Git%20%E7%9B%AE%E5%BD%95.png)
工作区是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。
Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。
基本的 Git 工作流程如下:
1. 在工作区中修改文件。
2. 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。
3. 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。
如果 Git 目录中保存着特定版本的文件,就属于 **已提交** 状态。 如果文件已修改并放入暂存区,就属于 **已暂存** 状态。 如果自上次检出后,作了修改但还没有放到暂存区域,就是 **已修改** 状态。
#### 工作区和版本库
Git本地有三个工作区域:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)。如果在加上远程的git仓库(Remote Directory)就可以分为四个工作区域。文件在这四个区域之间的转换关系如下:
![工作区暂存区.git文件夹图示](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/%E5%B7%A5%E4%BD%9C%E5%8C%BA%E6%9A%82%E5%AD%98%E5%8C%BA.git%E6%96%87%E4%BB%B6%E5%A4%B9%E5%9B%BE%E7%A4%BA.png)
- Workspace:工作区,就是你平时存放项目代码的地方
- Index / Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息
- Repository:仓库区(或本地仓库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本
- Remote:远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换
##### 工作区(Working Directory)
就是你在电脑里能看到的目录
![工作区解释](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/%E5%B7%A5%E4%BD%9C%E5%8C%BA%E8%A7%A3%E9%87%8A.png)
##### 版本库(Repository)
工作区有一个隐藏目录`.git`,这个文件夹就是Git的版本库。
我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用`git add`把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用`git commit`提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个`master`分支,所以,现在,`git commit`就是往`master`分支上提交更改。
##### 暂存区
为了理解暂存区的概念 我们介绍一个命令
> git status
首先我们在工作区新建一个文件叫做 `abc.txt`然后进行`git add`命令提交
最后执行 `git status` 命令,你会发现 有一个文件没有提交
我们再次执行 `git commit -m "add a file named abc.txt"` 然后执行 `git status` 会发现暂存区空了
所有文件都已经提交上去了
```powershell
> git add abc.txt
> git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: abc.txt
> git commit -m "add a file named abc.txt"
[master 4826a32] add a file named abc.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 abc.txt
> git status
On branch master
nothing to commit, working tree clean
```
###### git status输出简短信息
`git status` 命令的输出十分详细,但其用语有些繁琐。 Git 有一个选项可以帮你缩短状态命令的输出,这样可以以简洁的方式查看更改。 如果你使用 `git status -s` 命令或 `git status --short` 命令,你将得到一种格式更为紧凑的输出。
```powershell
> git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
```
新添加的未跟踪文件前面有 `??` 标记,新添加到暂存区中的文件前面有 `A` 标记,修改过的文件前面有 `M` 标记。 输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。例如,上面的状态报告显示: `README` 文件在工作区已修改但尚未暂存,而 `lib/simplegit.rb` 文件已修改且已暂存。 `Rakefile` 文件已修,暂存后又作了修改,因此该文件的修改中既有已暂存的部分,又有未暂存的部分。
### git基本使用(入门)
#### git帮助
若你使用 Git 时需要获取帮助,有三种等价的方法可以找到 Git 命令的综合手册(manpage):
```powershell
git help <verb>
git <verb> --help
man git-<verb>
```
此外,如果你不需要全面的手册,只需要可用选项的快速参考,那么可以用 `-h` 选项获得更简明的 “help” 输出:
```powershell
git add -h
usage: git add [<options>] [--] <pathspec>...
-n, --dry-run dry run
-v, --verbose be verbose
-i, --interactive interactive picking
-p, --patch select hunks interactively
-e, --edit edit current diff and apply
-f, --force allow adding otherwise ignored files
-u, --update update tracked files
--renormalize renormalize EOL of tracked files (implies -u)
-N, --intent-to-add record only the fact that the path will be added later
-A, --all add changes from all tracked and untracked files
--ignore-removal ignore paths removed in the working tree (same as --no-all)
--refresh don't add, only refresh the index
--ignore-errors just skip files which cannot be added because of errors
--ignore-missing check if - even missing - files are ignored in dry run
--chmod (+|-)x override the executable bit of the listed files
--pathspec-from-file <file>
read pathspec from file
--pathspec-file-nul with --pathspec-from-file, pathspec elements are separated with NUL character
```
#### 克隆版本库
> git clone 仓库地址(例如 https://github.com/libgit2/libgit2) 克隆下的仓库的名字
```powershell
git clone https://github.com/libgit2/libgit2 myFirstCloneProject
Cloning into 'myFirstCloneProject'...
remote: Enumerating objects: 105276, done.
remote: Counting objects: 100% (105276/105276), done.
remote: Compressing objects: 100% (28809/28809), done.
remote: Total 105276 (delta 74605), reused 105273 (delta 74602), pack-reused 0 eceiving objects: 100% (105276/105276), 5Receiving objects: 100% (105276/105276), 52.77 MiB | 3.52 MiB/s, done.
Resolving deltas: 100% (74605/74605), done.
Updating files: 100% (10369/10369), done.
```
#### 创建版本库
版本库又名仓库,英文名**repository**,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
```shell
> git init
Initialized empty Git repository in F:/project/gitRepository/.git/
```
注意点
所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
#### 新建文件
新建一个文件叫做README.txt 的文件 里边写入 `hello world`
如果你此时使用命令
> git status #下边会介绍这个命令
```powershell
> git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.txt
```
从这里可以看出 这个 README.txt 文件并没有被追踪
#### 添加文件到git仓库中去
>git add README.txt
再次使用**git status**命令
```powershell
> git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.txt
```
这里 README.txt已经是被追踪状态
#### 把文件提交到仓库
>git commit -m "add a readme file"
-m 的含义是添加一个注释 最好每次提交都要进行添加注释
```powershell
> git commit -m "add a readme file"
[master (root-commit) d72679f] add a readme file
1 file changed, 1 insertion(+)
create mode 100644 README.txt
```
再次使用**git status**命令
```powershell
> git status
On branch master
nothing to commit, working tree clean
```
这个时候暂存区没有东西 都提交到版本库中去了
#### 版本回退
首先在README.txt 文件中添加 `yhn` 文本 ,然后执行添加文件和提交到仓库命令
```powershell
> git add README.tx
> git commit -m "add word yhn"
[master e37f1ba] add word yhn
1 file changed, 1 insertion(+), 1 deletion(-)
```
##### 查看文件的修改记录
查看文件的修改记录有两个关注点 一个是 类似 `e37f1ba110b0a3118d78a69fa4ea08b804cb29b5`的字符串,因为它代表了一个特定的版本,对以后进行项目的回滚意义重大。 下面我们介绍 `git log`命令
> git log
`git log`不传入任何参数的默认情况下,`git log` 会按时间先后顺序列出所有的提交,最近的更新排在最上面。 正如你所看到的,这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。
```powershell
> git log
commit e37f1ba110b0a3118d78a69fa4ea08b804cb29b5 (HEAD -> master)
Author: 你的名字 <你的邮箱地址>
Date: Thu Jul 23 14:02:49 2020 +0800
add word yhn
commit d72679f8240c969998dd4fd4b4f3bbe35ea1a8e5
Author: 你的名字 <你的邮箱地址>
Date: Thu Jul 23 13:54:34 2020 +0800
add a readme file
#下边这句命令就将文件还原为一开始当初README.txt 内只含有 hello world 文件
> git reset --hard e37f1ba110b0a3118d78a69fa4ea08b804cb29b5
HEAD is now at e37f1ba add word yhn
```
`git log` 有许多选项可以帮助你搜寻你所要找的提交
其中一个比较有用的选项是 `-p` 或 `--patch` ,它会显示每次提交所引入的差异(按 **补丁** 的格式输出)。 你也可以限制显示的日志条目数量,例如使用 `-1` 选项来只显示最近的一次提交:
```powershell
> git log -p -1
commit 65269d31ce13ce3feed806b224bf65f429698b54 (HEAD -> master)
Author: 你的名字 <你的邮箱>
Date: Fri Jul 24 12:11:30 2020 +0800
rename a file named abc.txt to efg.txt
diff --git a/abc.txt b/efg.txt
similarity index 100%
rename from abc.txt
rename to efg.txt
```
| 选项 | 说明 |
| :---------------- | :----------------------------------------------------------- |
| `-p` | 按补丁格式显示每个提交引入的差异。 |
| `--stat` | 显示每次提交的文件修改统计信息。 |
| `--shortstat` | 只显示 --stat 中最后的行数修改添加移除统计。 |
| `--name-only` | 仅在提交信息后显示已修改的文件清单。 |
| `--name-status` | 显示新增、修改、删除的文件清单。 |
| `--abbrev-commit` | 仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。 |
| `--relative-date` | 使用较短的相对时间而不是完整格式显示日期(比如“2 weeks ago”)。 |
| `--graph` | 在日志旁以 ASCII 图形显示分支与合并历史。 |
| `--pretty` | 使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和 format(用来定义自己的格式)。 |
| `--oneline` | `--pretty=oneline --abbrev-commit` 合用的简写。 |
`git log` 也可以进行筛选 下边是其具体命令
| 选项 | 说明 |
| :-------------------- | :----------------------------------------- |
| `-<n>` | 仅显示最近的 n 条提交。 |
| `--since`, `--after` | 仅显示指定时间之后的提交。 |
| `--until`, `--before` | 仅显示指定时间之前的提交。 |
| `--author` | 仅显示作者匹配指定字符串的提交。 |
| `--committer` | 仅显示提交者匹配指定字符串的提交。 |
| `--grep` | 仅显示提交说明中包含指定字符串的提交。 |
| `-S` | 仅显示添加或删除内容匹配指定字符串的提交。 |
```powershell
git log --since "2020-07-23"
```
##### 向前回滚文件
> git reset --hard HEAD~1
HEAD的意思是指针 ,上述命令将文件回滚到上一个版本,HEAD~1 的1可以修改为任意正值 ,前提是前边的版本存在
```powershell
> git reset --hard HEAD~1
HEAD is now at d72679f add a readme file
```
如果你回滚到了上一个版本结果后悔了 下边的内容可以解决你的问题
##### 指定版本进行复原
知道了指定版本的hash值 我们就可以还原时间线上任意的版本了
> git reset --hard 版本hash值
```powershell
> git log -p -1
commit 65269d31ce13ce3feed806b224bf65f429698b54 (HEAD -> master)
Author: 你的名字 <你的邮箱>
Date: Fri Jul 24 12:11:30 2020 +0800
rename a file named abc.txt to efg.txt
diff --git a/abc.txt b/efg.txt
similarity index 100%
rename from abc.txt
rename to efg.txt
commit 897277b6a76d3044077e37822dfecd52c6c11809
Author: 你的名字 <你的邮箱>
Date: Fri Jul 24 11:51:54 2020 +0800
modified README.txt and abc.txt"
diff --git a/README.txt b/README.txt
index e862673..6c08837 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1,2 @@
hello world yhn
+<E5><9C><A8><E6><98><AF><E7><A8><8B><E5><BA><8F><E6><B1><A0>vdssdf
\ No newline at end of file
diff --git a/abc.txt b/abc.txt
index e69de29..c2e06b7 100644
--- a/abc.txt
+++ b/abc.txt
@@ -0,0 +1 @@
+gfdzgdxgdfxg
\ No newline at end of file
> git reset --hard 897277b6a
HEAD is now at 897277b modified README.txt and abc.txt
```
##### git命令的重现
如果你的电脑关机或者是关闭了命令行工具,结果导致你后悔了你的回退决定 ,可以调用
> git reflog
这个命令可以查看你所有的已经执行的操作 这样你就可以发现你的文件id了 通过执行`指定版本进行复原`的命令 可以重新回到未回滚的状态了
```powershell
> git reflog
e37f1ba (HEAD -> master) HEAD@{0}: reset: moving to e37f1ba110b0a3118d78a69fa4ea08b804cb29b5
e37f1ba (HEAD -> master) HEAD@{1}: reset: moving to e37f1ba110b0a3118d78a69fa4ea08b804cb29b5
d72679f HEAD@{2}: reset: moving to HEAD~1
e37f1ba (HEAD -> master) HEAD@{3}: reset: moving to e37f1ba110b0a3118d78a69fa4ea08b804cb29b5
d72679f HEAD@{4}: reset: moving to HEAD^
e37f1ba (HEAD -> master) HEAD@{5}: reset: moving to HEAD
e37f1ba (HEAD -> master) HEAD@{6}: reset: moving to e37f1ba110b0a3118d78a69fa4ea08b804cb29b5
d72679f HEAD@{7}: reset: moving to d72679f8240c969998dd4fd4b4f3bbe35ea1a8e5
e37f1ba (HEAD -> master) HEAD@{8}: reset: moving to e37f1ba110b0a3118d78a69fa4ea08b804cb29b5
d72679f HEAD@{9}: reset: moving to d72679f8240c969998dd4fd4b4f3bbe35ea1a8e5
d72679f HEAD@{10}: reset: moving to d7267
d72679f HEAD@{11}: reset: moving to HEAD^
e37f1ba (HEAD -> master) HEAD@{12}: reset: moving to HEAD
e37f1ba (HEAD -> master) HEAD@{13}: commit: add word yhn
d72679f HEAD@{14}: commit (initial): add a readme file
```
##### HEAD指针的作用
```powershell
回滚之前
┌────┐
│HEAD│
└────┘
│
│ ○ add a readme file
│ │
└── >○ add word yhn
回滚之后
┌────┐
│HEAD│
└────┘
│
└──> ○ add a readme file
│
○ add word yhn
```
### git 查看不同版本区别 (diff命令 )
为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是`修改`,而非文件。
你会问,什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。
> git diff HEAD -- 要查看的文件名称
上边这个命令可以让我们对比当前文件和版本库中文件的区别
```powershell
> git diff HEAD -- README.txt
diff --git a/README.txt b/README.txt
index e862673..8488128 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1,2 @@
hello world yhn
+fgsdgsdgsgfsdg
\ No newline at end of file
```
从上方可以看出来 我添加了文本`fgsdgsdgsgfsdg`
##### 当前文件和暂存区域快照差异
要查看尚未暂存的文件更新了哪些部分,不加参数直接输入
> git diff
```powershell
> git diff
diff --git a/README.txt b/README.txt
index e862673..6c08837 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1,2 @@
hello world yhn
+<E5><9C><A8><E6><98><AF><E7><A8><8B><E5><BA><8F><E6><B1><A0>vdssdf
\ No newline at end of file
diff --git a/abc.txt b/abc.txt
index e69de29..c2e06b7 100644
--- a/abc.txt
+++ b/abc.txt
@@ -0,0 +1 @@
+gfdzgdxgdfxg
\ No newline at end of file
```
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异。 也就是修改之后还没有暂存起来的变化内容。
##### 已暂存文件与最后一次提交的文件差异
若要查看已暂存的将要添加到下次提交里的内容,可以用
> git diff --staged
命令。 这条命令将比对已暂存文件与最后一次提交的文件差异:
`--staged` 和 `--cached` 是同义词
### git文件操作
#### git 删除文件(直接删除硬盘上文件)
> git rm 文件名
```powershell
> git rm abc.txt
rm 'abc.txt'
> git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: abc.txt
> git commit -m "delete abc.txt"
[master 5b3dfd2] delete abc.txt
1 file changed, 1 deletion(-)
delete mode 100644 abc.txt
> git status
On branch master
nothing to commit, working tree clean
```
如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 `-f`(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复
#### git移除文件(不被git跟踪)
> git rm --cached 文件名
```powershell
> git rm --cached abc.txt
rm 'abc.txt'
> git commit -m "untracked file abc.txt"
[master ffb9a4a] untracked file abc.txt
1 file changed, 1 deletion(-)
delete mode 100644 abc.txt
> git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
abc.txt
nothing added to commit but untracked files present (use "git add" to track)
```
#### git 重命名文件
> git mv 原文件名称 更改后文件名称
```powershell
> git mv abc.txt efg.txt
> git commit -m "rename a file named abc.txt to efg.txt"
[master 65269d3] rename a file named abc.txt to efg.txt
1 file changed, 0 insertions(+), 0 deletions(-)
rename abc.txt => efg.txt (100%)
> git status
On branch master
nothing to commit, working tree clean
```
其实,运行 `git mv` 就相当于运行了下面三条命令:
```powershell
在文件夹中直接把 abc.txt 文件名称修改为 efg.txt
> git rm abc.txt
> git add efg.txt
```
如此分开操作,Git 也会意识到这是一次重命名,所以不管何种方式结果都一样。 两者唯一的区别是,`mv` 是一条命令而非三条命令,直接用 `git mv` 方便得多。 不过有时候用其他工具批处理重命名的话,要记得在提交前删除旧的文件名,再添加新的文件名。
#### git忽略文件 .gitigonre
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 `.gitignore` 的文件,列出要忽略的文件的模式。 来看一个实际的 `.gitignore` 例子:
```shell
# 忽略所有的 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdfxxxxxxxxxx
```
文件 `.gitignore` 的格式规范如下:
- 所有空行或者以 `#` 开头的行都会被 Git 忽略。(注释)
- 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
- 匹配模式可以以(`/`)开头防止递归。
- 匹配模式可以以(`/`)结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(`!`)取反。
### git撤销操作
#### git第二次提交代替第一次提交
先将工作区中的`README.txt` 和 `abc.txt `文件添加上一些字符
这次主要介绍以下命令
> git commit --amend
如果提交的时候忘记提交`abc.txt`文件了利用` git commit --amend`命令来补救一下
```powershell
> git status # 这里看出我修改了 README.txt 和 abc.txt 文件
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.txt
modified: abc.txt
no changes added to commit (use "git add" and/or "git commit -a")
> git add README.txt #这里我只把README.txt 加入进来 没有 abc.txt
> git commit -m "modify README.txt and abc.txt" # 直接提交了
[master a06a6f6] modify README.txt and abc.txt
1 file changed, 3 insertions(+), 1 deletion(-)
> git add abc.txt # 先把abc.txt 加进来 补救一下
> git commit --amend #覆盖第一个commit命令 执行这个 这里会跳出来一个文本框 可以修改注释
[master 17a4e64] modify README.txt and abc.txt
Date: Fri Jul 24 14:27:50 2020 +0800
2 files changed, 5 insertions(+), 2 deletions(-)
```
#### git移除文件(取消git add命令)
> git restore --staged 文件名称
```powershell
> git status #这里看出 两个文件都被修改 如果此时执行 git commit 那么两个文件都会被提交
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.txt
modified: abc.txt
no changes added to commit (use "git add" and/or "git commit -a")
> git add * #两个文件都纳入暂存区
> git restore --staged abc.txt
> git status # 这里可以看出 如果执行git commit 只有README.txt 会被纳入仓库
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: abc.txt
```
#### git 将文件恢复到上一次提交的状态
> git restore 文件名
接上方的命令
```powershell
> git status #这里abc.txt 没有进行 git add 命令
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: abc.txt
> git restore abc.txt #将abc.txt 文件恢复到上次提交状态
> git status #可以看出这时 abc.txt 没有进行修改
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.txt
```
### git远程仓库的使用
你完全可以在一个“远程”仓库上工作,而实际上它在你本地的主机上。 词语“远程”未必表示仓库在网络或互联网上的其它位置,而只是表示它在别处。 在这样的远程仓库上工作,仍然需要和其它远程仓库上一样的标准推送、拉取和抓取操作。
#### 克隆仓库
>git clone 仓库地址
```powershell
> git clone https://github.com/99611400/LeetCodeAnimation.git
Cloning into 'LeetCodeAnimation'...
remote: Enumerating objects: 566, done.
Rremote: Total 566 (delta 0), reused 0 (delta 0), pack-reused 566 Receiving objects: 100% (566/566), 116.00 KiB | 215.00 KiB/s
Receiving objects: 100% (566/566), 216.39 KiB | 232.00 KiB/s, done.
Resolving deltas: 100% (234/234), done.
```
#### git remote 命令
如果想查看你已经配置的远程仓库服务器,可以运行 `git remote` 命令。 它会列出你指定的每一个远程服务器的简写。 如果你已经克隆了自己的仓库,那么至少应该能看到 origin ——这是 Git 给你克隆的仓库服务器的默认名字:
> git remote
```powershell
> git remote
origin
```
你也可以指定选项 `-v`,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。
> git remote -v
```powershell
> git remote -v
origin https://github.com/99611400/LeetCodeAnimation.git (fetch)
origin https://github.com/99611400/LeetCodeAnimation.git (push)
```
> git remote add 别名 url
```powershell
> git remote add pb https://github.com/paulboone/ticgit
> git remote -v
origin https://github.com/99611400/LeetCodeAnimation.git (fetch)
origin https://github.com/99611400/LeetCodeAnimation.git (push)
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push)
```
#### 本地仓库和远程仓库连接
因为要想让git本地仓库和github的仓库连接起来正规操作我还是不会操作,一个简单的小技巧可以方便的完成这个过程
##### 创建ssh公钥和私钥
注意 : 执行下方命令的前提是你的电脑已经安装了`git`
在cmd中输入
> ssh-keygen
```shell
> ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\你的电脑用户名/.ssh/id_rsa): #询问你将密钥文件存到哪里
Enter passphrase (empty for no passphrase): #输入访问密码 如果为空那么无密码
Enter same passphrase again:
Your identification has been saved in C:\Users\你的电脑用户名/.ssh/id_rsa.
Your public key has been saved in C:\Users\你的电脑用户名/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:TXcOZM2Q6MPgotEQnP8MQSWrR6L1RhEU6Nu4uzAAwbE 你的电脑用户名@你的电脑名称
The key's randomart image is:
+---[RSA 2048]----+
|o....*B+. .+= |
| o. = .+. .o. o |
|.E .o++o +. o . |
|. oo*= .o+. + |
|. . .*+=S .. . |
| . +o. o |
| o . |
| o. |
| oo |
+----[SHA256]-----+
```
公钥是用来提交给`github`或者是`gitee`这种平台,当你执行 `git push`这些命令的时候,你会联系服务器验证你的身份,证明你有权限操作`github`上存储的文件。具体原理如下
**公钥登录是为了解决每次登录服务器都要输入密码的问题**,流行使用RSA加密方案,主要流程包含:
1、客户端生成RSA公钥和私钥
2、客户端将自己的公钥存放到服务器
3、客户端请求连接服务器,服务器将一个随机字符串发送给客户端
4、客户端根据自己的私钥加密这个随机字符串之后再发送给服务器
5、服务器接受到加密后的字符串之后用公钥解密,如果正确就让客户端登录,否则拒绝。这样就不用使用密码了。
创建了公钥与私钥之后 我们需要将公钥提供给`github`。`gitee`的操作方式类似就不列举了
##### 公钥与私钥的生成地址
如果没有特别指定过(因为上面创建密钥有提示可以修改你存储密钥的地址) ,如果你是windows,一般是在**C:/users/你的电脑用户名/.ssh**目录下
##### 将本机添加`github`的公钥列表中去(让`github`认可你的电脑)
==以下图片是步骤==
![github远程仓库和本地仓库连接1](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/github%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%92%8C%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E8%BF%9E%E6%8E%A51.png)
![github远程仓库和本地仓库连接2](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/github%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%92%8C%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E8%BF%9E%E6%8E%A52.png)
![github远程仓库和本地仓库连接3](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/github%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%92%8C%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E8%BF%9E%E6%8E%A53.png)
![github远程仓库和本地仓库连接4](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/github%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%92%8C%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E8%BF%9E%E6%8E%A54.png)
![github远程仓库和本地仓库连接5](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/github%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%92%8C%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E8%BF%9E%E6%8E%A55.png)
#### 每次创建仓库让本机仓库和github仓库连接的小技巧
上述操作只是让你的电脑被github认可具有操作权限,可是本地的仓库并没有和github的仓库联系起来
当你新建一个仓库后的你需要直接把他克隆到你的本机
##### 新建一个仓库
![新建一个仓库1](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AA%E4%BB%93%E5%BA%93.png)
![复制仓库SSH地址](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/%E5%A4%8D%E5%88%B6%E4%BB%93%E5%BA%93SSH%E5%9C%B0%E5%9D%80.png)
##### 将项目克隆到本地
![将项目克隆到本地](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/git%E5%AD%A6%E4%B9%A0/%E5%B0%86%E9%A1%B9%E7%9B%AE%E5%85%8B%E9%9A%86%E5%88%B0%E6%9C%AC%E5%9C%B0.png)
经过克隆到本地操作之后 其实你的本地仓库和github的远程仓库已经联系起来了
此时输入命令
> git remote -v
```shell
> git remote -v
origin git@github.com:你的账户名/test.git (fetch)
origin git@github.com:你的账户名/test.git (push)
```
可以看出你的远程仓库的地址就是github的地址
此时你直接把文件复制进去 执行 git add git commit 最后直接执行git push 就能将所有东西上传到github上去
##### git push命令
先新建一个文件 叫做` gitPushTest.txt` 然后执行以下命令
```shell
> git status
On branch master
Your branch is up to date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
gitPushTest.txt
nothing added to commit but untracked files present (use "git add" to track)
> git add gitPushTest.txt
> git commit -m "git push test"
[master b6c4a98] git push test
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 gitPushTest.txt
> git push #这里不需要输入密码即可直接推送到github仓库 主要是ssh公钥和私钥在起到验证身份的作用
Warning: Permanently added the RSA host key for IP address '13.229.188.59' to the list of known hosts.
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 6 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 274 bytes | 274.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:99611400/test.git
25ade13..b6c4a98 master -> master
```
### git 分支操作
#### **Git branch**
**下边的例子只是一种情况 不同的仓库显示也不一样 只是个例子**
一般用于分支的操作,比如创建分支,查看分支等等,
1. git branch
```shell
> git branch
* main
```
不带参数:列出本地已经存在的分支,并且在当前分支的前面用"*"标记
2. git branch -r
```shell
> git branch -r
origin/HEAD -> origin/main
origin/main
```
查看远程版本库分支列表
3. git branch -a
```shell
> git branch -a
* main
remotes/origin/HEAD -> origin/main
remotes/origin/main
```
查看所有分支列表,包括本地和远程
4. git branch dev
```shell
> git branch dev
> git branch -a
dev
* main
remotes/origin/HEAD -> origin/main
remotes/origin/main
```
创建名为dev的分支,创建分支时需要是最新的环境,创建分支但依然停留在当前分支
5. git branch -d dev
```shell
> git branch -d dev
Deleted branch dev (was 142738a).
```
删除dev分支,如果在分支中有一些未merge的提交,那么会删除分支失败,此时可以使用 git branch -D dev:强制删除dev分支,
6. git branch -vv
```shell
* main 142738a [origin/main] xxxxxxxx
----------------------------------------------------------
aaaa 6410227 [origin/aaaa] xxxxxxxxx
* master 1797796 [origin/master] xxxxxxxxx
bbbb 6410227 [origin/bbbb] xxxxxxxxx
cccc 8304063 [origin/cccc] xxxxxxxxx
```
可以查看本地分支对应的远程分支
7. git branch -m oldName newName
```shell
> git branch dev
> git branch -m dev devtest
> git branch
devtest
* main
```
给分支重命名
#### Git checkout
1. 操作文件 2. 操作分支
1操作文件
git checkout -- filename 放弃单个文件的修改
git checkout . 放弃当前目录下的修改
2操作分支
git checkout master 将分支切换到master
```shell
> git checkout devtest
Switched to branch 'devtest'
```
git checkout -b master 如果分支存在则只切换分支,若不存在则创建并切换到master分支,repo start是对git checkout -b这个命令的封装,将所有仓库的分支都切换到master,master是分支名,
```shell
> git checkout -b test
Switched to a new branch 'test'
> git branch -a
devtest
main
* test
remotes/origin/HEAD -> origin/main
remotes/origin/main
```
### git的reset和checkout的区别
([git的reset和checkout的区别 - SegmentFault 思否](https://segmentfault.com/a/1190000006185954))
在讲git的reset和checkout的区别之前,不得不说说HEAD、Index、Working Directory三个区域。
#### 初始状态
当你checkout分支的时候,git做了这么三件事情
1. 将HEAD指向那个分支的最后一次commit
2. 将HEAD指向的commit里所有文件的snapshot替换掉Index区域里原来的内容
3. 将Index区域里的内容填充到Working Directory里
所以你可以发现,HEAD、Index、Working Directory这个时候里的内容都是一模一样的。
**注意**:一般会误解为,Index中的内容是空的,只有git add后才会有东西。实际上不是,Index里一直是有东西的。
所以,Git的所有操作就是对这三个区域的状态(或内容)的操作。
#### Changed
如果你在Working Directory(工作区)里修改了文件,git会发现Working Directory里的内容和Index区域里的内容不一致了。
这个时候git status的结果是:
```shell
# Changes not staged for commit:
```
#### Staged
一个文件仅仅changed是不能被commit的,Git要求只能提交Index里的东西。
所以需要git add。这个命令的意思是,把Changed的文件的内容同步到Index区域里。这样Working Directory和Index区域的内容就一致了。这个过程被称之为stage
这个时候git status的结果是:
```
# Changes to be committed:
```
#### Committed
最后,你就可以提交了
git commit
这样,就把HEAD的状态和Index以及Working Directory形成一致了。
#### reset
reset是用来修改提交历史的,想象这种情况,如果你在2天前提交了一个东西,突然发现这次提交是有问题的。
这个时候你有两个选择,要么使用git revert(推荐),要么使用git reset。
![image-20210720222623213](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/typoraimage-20210720222623213.png)
上图可以看到git reset是会**修改**版本历史的,他会丢弃掉一些版本历史。
而git revert是根据那个commit逆向生成一个新的commit,版本历史是不会被破坏的。
#### 已经push到远程仓库的commit不允许reset
上面已经讲了,git reset是会丢弃掉commit的。
如果commit已经被push到远程仓库上了,也就意味着其他开发人员就可能基于这个commit形成了新的commit,这时你去reset,就会造成其他开发人员的提交历史莫名其妙的丢失,或者其他灾难性的后果。
**因此,一旦commit已经被push到远程仓库,那么是坚决不允许去reset它的。**
#### 不带文件参数的reset
前面章节已经说道Git有三个区域,Git的所有操作实际上是在操作这三个区域的状态(或内容)。
git reset配合不同的参数,对这三个区域会产生不同的影响。
reset实际上有3个步骤,根据不同的参数可以决定执行到哪个步骤(`--soft`, `--mixed`, `--hard`)。
1. 改变HEAD所指向的commit(`--soft`)
2. 执行第1步,将Index区域更新为HEAD所指向的commit里包含的内容(`--mixed`)
3. 执行第1、2步,将Working Directory区域更新为HEAD所指向的commit里包含的内容(`--hard`)
**注意**
`–mixed`是默认参数,也就是说执行reset的时候不给就认为是`--mixed`。
下表说明了三种形式的git reset所产生的不同效果。
**target代表想要将git指向到哪个commit**
```shell
#这个表的意思是执行 git reset --soft (或者--mixed 或--hard) D
working index HEAD target working index HEAD
----------------------------------------------------
A B C D --soft A B D
--mixed A D D
--hard D D D
--merge (disallowed)
#这个表的意思是执行 git reset --soft (或者--mixed 或--hard) C
working index HEAD target working index HEAD
----------------------------------------------------
A B C C --soft A B C
--mixed A C C
--hard C C C
--merge (disallowed)
```
#### 带文件参数的reset
上面讲到的git reset实际上不带参数的,如果带上文件参数,那么效果会是怎样的?
1. HEAD不会动
2. 将那个commit的snapshot里的那个文件放到Index区域中
需要注意的是带文件参数的git reset没有--hard, --soft这两个参数。只有--mixed参数。
#### unstage
下面这两个命令是一样的,都是reset到HEAD上。
```
git reset file.txt
git reset --mixed HEAD file.txt
```
#### 恢复到历史版本
下面这个命令就是将某个文件恢复到历史版本上。
```
reset eb43bf file.txt
```
这个例子的意思在于,把某个文件恢复到Index区域里,然后直接commit,这样就等于把这个文件恢复到历史版本了,这样依赖你都不需要去改动Working Directory了。
#### checkout
前面讲到checkout是会修改HEAD的指向,变更Index区域里的内容,修改Working Directory里的内容。
这看上去很像`reset --hard`,但和`reset --hard`相比有两个重要的差别
1. reset会把working directory里的所有内容都更新掉
2. checkout不会去修改你在Working Directory里修改过的文件
3. reset把branch移动到HEAD指向的地方
4. checkout则把HEAD移动到另一个分支
第二个区别可能有点难以理解,举例来说:假设你有两个分支master和develop,这两个分支指向不一样的commit,我们现在在develop分支上(HEAD指向的地方)
如果我们`git reset master`,那么develop就会指向master所指向的那个commit。
如果我们`git checkout master`,那么develop不会动,只有HEAD会移动。HEAD会指向master。看图:
![image-20210720223535549](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/typoraimage-20210720223535549.png)
#### 带文件参数
当执行git checkout [branch] file时,checkout干了这件事情:
1. 更新了index区域里file文件的内容
2. 更新了working directory里file文件的内容
#### 总结reset和checkout
```
head index work dir wd safe
Commit Level
reset --soft [commit] REF NO NO YES
reset [commit] REF YES NO YES
reset --hard [commit] REF YES YES NO
checkout [commit] HEAD YES YES YES
File Level
reset (commit) [file] NO YES NO YES
checkout (commit) [file] NO YES YES NO
```
“head”一列中的“REF”表示该命令移动了HEAD指向的分支引用,而“HEAD”则表示只移动了HEAD自身。 特别注意 “wd safe?” 一列,YES表示不会懂你在work dir的修改,NO代表会动你在work dir的修改。
### git jetbrain全家桶中的合并分支 图形化操作
当前分支是master 如果想要将 wen的分支的内容合并到master直接点击
![image-20210720224719331](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/typoraimage-20210720224719331.png)
![image-20210720224941028](https://tuchuang1234.oss-cn-shenzhen.aliyuncs.com/typoraimage-20210720224941028.png)
如果没有冲突,最后只需要在master执行一下git push 就可以进行远程推送了
git学习