# Git基础(二)

在[Git基础(一)](https://rodneycheung.gitbook.io/handbook/2.-huan-jing-pian/gong-ju-bu-shu-he-shi-yong/ban-ben-kong-zhi/git/1.-ji-chu/1_git_fundamental)中简单描述了git的常用的生命周期及操作，现在对这些操作进行更深入的描述。

## 一、查看当前仓库状态

使用`git status`可以查看当前仓库的状态，它也可以加上`--short`或者`-s`参数，这样输出就会显得非常简洁。

```
 D 2.环境篇/工具部署和使用/开发工具/git/1.基础/git_fundamental.md
?? 2.环境篇/工具部署和使用/开发工具/git/1.基础/1_git_fundamental.md
?? 2.环境篇/工具部署和使用/开发工具/git/1.基础/2_git_fundamental.md
```

在每个文件前都会有一个字符串来标记该文件的状态，其中：

```
??表示新增未跟踪文件
D 表示该文件被删除
```

此时，当我们使用`git add`将所有修改添加到暂存区后，再次运行`git status -s`查看结果。

```
R  2.环境篇/工具部署和使用/开发工具/git/1.基础/git_fundamental.md -> 2.环境篇/工具部署和使用/开发工具/git/1.基础/1_git_fundamental.md
A  2.环境篇/工具部署和使用/开发工具/git/1.基础/2_git_fundamental.md
```

其中:

```
R表示该文件被重命名了
A表示该文件被新增到暂存区，git开始跟踪他的变化
```

接着，我们修改`2.环境篇/工具部署和使用/开发工具/git/1.基础/2_git_fundamental.md`的内容，然后再次使用`git status -s`来观察这些文件的状态。

```
R  2.环境篇/工具部署和使用/开发工具/git/1.基础/git_fundamental.md -> 2.环境篇/工具部署和使用/开发工具/git/1.基础/1_git_fundamental.md
AM 2.环境篇/工具部署和使用/开发工具/git/1.基础/2_git_fundamental.md
```

可以看到该文件的`A`右边多了一个`M`，表示该文件已经修改，但是还未添加到暂存区。回忆上一章的内容，当我们修改了文件然后添加到暂存区，再修改后，`git status`的输出。在`-s`选项中，`git`用一种十分优雅的方式表达了这一结果，当`M`位于左侧时，表示该文件有一些修改已经添加到暂存区。而当`M`位于右侧时，表示该文件还有修改未被添加到暂存区。

依此类推，如果该文件是一个已经被`git`仓库跟踪的文件，在进行`修改->添加到暂存区->再修改`的操作后，对于该文件，`git status -s`的输出是什么呢？

## 二、避免将垃圾引入git仓库

当我们的项目中存在一些不应该添加到仓库中的文件时，应该使用`.gitignore`文件来将垃圾都排除在项目之外。

`git`通过在项目目录中使用`.gitignore`文件来管理该项目需要跟踪的文件，一般我们在项目的根目录使用该文件，子目录的`.gitignore`会覆盖父目录的结果。

`.gitignore`的格式为：

* 所有空行或者以`#`开头的行都会被`Git`忽略。
* 可以使用标准的`glob`模式匹配。
* 匹配模式可以以`/`开头防止递归。
* 匹配模式可以以`/`结尾指定目录。
* 要忽略指定模式以外的文件或目录，可以在模式前加上惊叹号`!`取反。

> 所谓的`glob`模式是指`shell`所使用的简化了的正则表达式。`*`匹配零个或多个任意字符；`[abc]`匹配任何一个列在方括号中的字符（这个例子要么匹配一个 a，要么匹配一个 b，要么匹配一个 c）；问号`?`只匹配一个任意字符；如果在方括号中使用短划线分隔两个字符，表示所有在这两个字符范围内的都可以匹配（比如\[0-9] 表示匹配所有 0 到 9 的数字）。使用两个星号（*) 表示匹配任意中间目录，比如\`a/\**/z`可以匹配`a/z,a/b/z`或`a/b/c/z\`等。

一个简单的例子:

```python
# 忽略所有扩展名为.a的文件
*.a
# 除了lib.a
!lib.a
# 只忽略当前目录的libssl.a，不会忽略子目录中的libssl.a
/libssl.a
# 忽略所有build目录中的文件
build/
# 忽略doc中所有的txt文件
doc/*.txt
# 忽略doc及其子目录中所有的pdf文件
doc/**/*.pdf
```

## 三、查看当前修改内容

使用`git diff`命令可以查看当前工作区和暂存区之间的差异，**注意，这里不是工作区和之前一个commit的差异，而是工作区和暂存区的差异，也就是一个文件修改后暂存后的文件快照和再次修改之后的差异。**

如果想查看已经暂存的和上一次提交的差异，可以使用`git diff --staged`。

## 四、提交暂存区内容

当文件被`git add`添加到暂存区后还需要使用`git commit`来将代码提交到本地仓库中，前面已经使用了`git commit -m`来为提交添加一个信息，表示本次提交的内容。一般来说，这个信息不应太长，应言简意赅地描述本次改动的内容。如果条件允许，最好再通过一个`CHANGELOG`文件来详细描述本次改动，这对于版本追溯十分有帮助。如果你不想使用`-m`选项，可以在之前配置的默认编辑器中增加这些信息。

```
Develop | add git fundamental 2
# enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
#       renamed:    2.环境篇/工具部署和使用/开发工具/git/1.基础/git_fundamental.md -> 2.环境篇/工具部署和使用/开发工具/git/1.基础/1_git_fundamental.md
#       new file:   2.环境篇/工具部署和使用/开发工具/git/1.基础/2_git_fundamental.md
#
# Changes not staged for commit:
#       modified:   2.环境篇/工具部署和使用/开发工具/git/1.基础/2_git_fundamental.md
#
```

在最上面一行写你的`commit message`，如果什么都不写，将会中断这次提交。

```
Aborting commit due to empty commit message.
```

完成后保存退出，这时显示提交已经完成。

```
[master 27ea6fc] Develop | add git fundamental 2
 2 files changed, 25 insertions(+), 3 deletions(-)
 rename 2.环境篇/工具部署和使用/开发工具/git/1.基础/{git_fundamental.md => 1_git_fundamental.md} (98%)
 create mode 100644 2.环境篇/工具部署和使用/开发工具/git/1.基础/2_git_fundamental.md
```

这时使用`git log`查看提交记录，可以看到:

```
commit 27ea6fc6f5459ebadadef99d937b8c0f973430e5 (HEAD -> master)
Author: zhanghaokang <zhanghaokang@antiy.cn>
Date:   Wed Nov 25 16:53:22 2020 +0800

    Develop | add git fundamental 2
```

刚刚的提交已经生效。

如果本次修改没有完成就提交了，想要再次将修改提交到仓库中，难道再次使用`git add -> git commit`吗？`git`新手会这样做，但是会在提交记录中生成两个提交记录，这样会污染提交记录，不利于以后版本回溯。那如果你觉得本次提交的`commit message`写的不太好，想要修改`commit message`，那么此时刚刚的方法将无法满足要求。

**正确的方法是将修改添加到暂存区后，使用`git commit --amend`来将本次修改合并到前一次提交。**

`--amend`参数用于弥补上一次提交缺失或者错误的内容，当你准备好提交后，使用`--amend`参数就会打开默认的编辑器，你可以在这里修改你的`commit message`。修改完成后，保存退出即刻生效。

使用`git log`来查看提交记录，可以看到:

```
commit c5a14321f8231aaaa13ae9d2db5dd8372260b6db (HEAD -> master)
Author: zhanghaokang <zhanghaokang@antiy.cn>
Date:   Wed Nov 25 16:53:22 2020 +0800

    Develop | add git fundamental amend
```

修改已经被合并到上一次修改中，且`commit message`完成修改。

类似的，如果不想进入默认的编辑器，只要同时使用`-m`参数，git就会将`commit message`替换为新的值。

```
git commit --amend -m "Develop | add git fundamental 2"
```

如果不小心进行了多次提交，这时使用`git commit --amend`就没办法了，此时需要`git rebase`命令来帮忙将多个提交合并到一起。对于这个操作，将在后面说到`rebase`的时候再细说。

还有个常用选项，如果不想执行`git add -A`这一步，那么可以使用`-a`选项，表示将所有修改添加到暂存区并进行提交。
