基本概念

1. 什么是版本控制系统

简单来说,有这么个东西它能帮你记录文件的变动的历史记录。支持这种功能的工具就叫版本控制系统( Verson Controll System )

这一类工具能将什么时候、谁、对什么文件做了怎样的修改这样的信息以版本的形式记录在案,以便支持你未来翻旧账。

Git 并非唯一的版本控制系统,Subversion 是它的前辈,2014 年 Git 的市场占有率首次超过 Subversion 。

2. 创建本地仓库 项目经理操作

Git 可以管理任何一个文件夹( 及其中内容 ),只要在该文件夹中执行 git init 命令,就可以让 Git 完成管理前的准备工作。

$ git init

执行成功后,你会看到类似如下信息:

Initialized empty Git repository in ...

从你执行 git init 命令这一刻开始 Git 就开始监控、监管这个文件夹下的文件的变动。这个文件夹( 它可以是一系列文件夹的根文件夹 )自此就成为了 Git 的一个 Repository

Git Repository下会被 Git 创建一个名为 .git 的子文件夹,这个文件夹也就是逻辑上的本地仓库。它里面会存放被 Git 所管理的文件的相关信息( 例如,历史版本 )

警告

你不要、不要、不要自己去动 .git 目录下的任何东西,更不要随意将 .git 目录删除。这个目录下的内容是 Git 来使用和操作的。

Git Repository 中的文件的变动( 新创建的、被删除的、内容有更新的 )都会被 Git 察觉。

提示

git init 命令让一个普通的文件夹变为了 Git 的一个 Repository ,而这种身份的变化之会发生一次,因此,毫无疑问对于一个项目而言,git init 命令只需要执行一次。

在 Gitkraken 中打开这个刚刚初始化的 Git 仓库,GitKraken 会要求你做一次初始化的提交:

git-GitKraken-01

提交之后效果如下:

git-GitKraken-02

3. Git 中的文件状态

提前说明

在 Git 中,严谨地来说,有一个专门的状态用来描述刚刚被新建出来的文件 untracked 未被追踪。即,所有被新建出来的文件都是 untracked 状态。

但是在日常使用中,这种状态和 unstanged 状态并没有太大区别,因此有些书、工具、文章为了便于初学者更快速理解、掌握 Git ,就将这两种状态合二为一,进行简化,都称为 unstaged 状态。

文件的状态变化(核心三态):

git-state.png

3.4 已提交( commited )状态

用单机游戏存档作类比的话,一个文件处于「已提交」状态类似于,你的角色刚刚存完档,正站在存档点。

此时此刻,你的人物的状态( 他在地图上的位置、他的经验值、他的红蓝条、他身上的装备、他背包里的金币数等等 )和最近的一次存档是完全一样的。

这种状态下,你和你的数据有 2 个特点:

  • 此时此刻,你应该是最踏实、最放心的时刻,你并不害怕突然断电这样会导致数据丢失的事故,因为你刚刚存完档。

  • 你最踏实最放心的第二个原因:此时此刻你还没有做任何「多」的事情,就算因为事故导致你取重新读档,你也没有任何「损失」。

「已提交」状态既是一轮轮操作的终点,又是下一轮操作的起点。

git-GitKraken-06

注意,如下图,git commit只会」将暂存区的文件( 即,staged / uncommited 文件 )的内容提交至本地仓库进行保存,以形成一个新的版本。

git-GitKraken-10

提交后,staged / uncommited 状态的文件会再一次变为 commited 状态。

git-commited-1

未提交状态:未暂存( Unstage )和已暂存( Staged )

还是以游戏的人物存档为例,「未提交」状态表示的是你的人物自上一次存档之后,他的状态发生了变化( 吃了个血包回血了、打了怪涨经验了、卡了个宝箱人品爆发出了个小极品、甚至就是往前走了两步导致在地图位置变化了),而你还没有进行新的、下一次存档。

本来文件的状态的变化本应是 未提交 -> 已提交 这样的 A -> B 型的变化。因为某些原因,Git 将 未提交状态又细分为 2 个阶段型状态:「未暂存」和「已暂存」。

这样文件的状态的变化就被设计成 未暂存 -> 已暂存 -> 已提交 这样的 A -> B -> C 型的变化。

  • 未暂存( unstaged )状态

    表示自上次提交之后有文件被「动过」。并且,顾名思义,Git 在提醒你:你应该暂存它。

    所谓的「动了」包括:新增文件、修改原有文件内容、删除已有文件等。

    对于 Unstaged 状态的文件,在 GitKraken 中你可以观察到它们:

    git-unstaged

  • 已暂存( staged )状态

    在 GitKraken 的图形化界面操作中,将 unstaged 状态的文件变为 staged / uncommited 状态的对应操作是:

    git-GitKraken-05

特殊状态:已忽略( ignored )状态 项目经理操作

Git Repository( 也就是上面所说的被 Git 管理的文件夹 )根目录下的 .gitignore 文件就是一个「黑名单」,在其中列举的文件如上所说,都不会被 Git 进行监管:Git 不会跟踪、记录这些文件的变动,跟不会将它们 push 到远程仓库。

java 项目的 .class 文件、maven 项目的 target 目录、nodejs 的 node_modules 目录都是应该加入到这个黑名单中的文件/目录。

.gitignore 文件必须叫 .gitignore ,一定不能错

提示

在 window 系统中,windows 不允许直接新建文件名以 . 开头的文件( Linux 不存在这个问题 )。因为,Windows 会误以为 .gitignore 是文件的后缀,而你的文件是没有名字的。Windows 不允许创建无名文件!

所以这种情况下,你需要「动脑子」创建。你可以在 git bash 中通过 touch 命令创建,也可以从别的项目中拷贝一个过来,还可以借助 vscode 在 vscode 中创建。

.gitignore 文件的基本语法

#  表示注释
/  目录层级
*  通配符

示例:

# 忽略所有后缀名为 log 的文件,无所谓文件名。无论它位于什么层次结构。
*.log

# 忽略 Git Repository「根目录」下的 target 文件夹
# 这里最后的 / 非必须。不过个人建议还是加上,因为可以暗示出它是一个文件夹。
/target/


# 忽略所有名为 target 的文件夹。无论它位于什么层次结构中。
target/

补充 .gitignore 文件中有一个 ! 表示的「非」的规则,对于它的使用相较而言比较复杂,暂时不要求掌握。

模板

### maven ###
target/
*.class

### nodejs ###
node_modules/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### VS Code ###
.vscode/

### Other ###
HELP.md
*.log
# virtual machine crash logs see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

注意事项

  1. .gitignore 配置文件的根目录就是当前 Git 工程目录。.gitignore 配置只对当前 Git 工程有效。

  2. 在配置语句的前后面添加空格、Tab、注释等,会导致当前行的配置语句失效。所以,不要添加非必要的空白符。

  3. 配置语句对已经提交过的文件无效,即,它只能影响未来,不能影响过去。

4. 提交

git add + git commit 的作用简单来说,就是将一个文件的变动提交给 Git 。

git add 命令可以将 unstaged 文件变为 staged 文件;git commit 命令可以将 staged 文件变为 commited 文件,从而完成了「存档」这个操作。

unstaged
└──> staged
     └──>  commited

注意

注意,没有办法将 unstaged 状态的文件直接变为 commited ,staged 是存档操作中文件状态变化的必经之路。

对于一次「提交」而言,提交消息(message)是必须的 。否则,Git 会拒绝你的这次提交。你存档时必须要说点啥

在 GitKraken 的图形化界面中,git commit 提交操作的功能在这个区域:

git-GitKraken-07

注意

一个完整的提交信息包括 header、body、footer 三部分,你至少要保证提供 header ,否则,你无法提交。

要新增「一次提交」之所以要同时使用 git addgit commit 是因为在将文件当前的内容添加成至本地仓库之前,要 将其添加至 暂存区

git-GitKraken-10

5. 翻旧账:读档

从本地版本库( .git )中取出文件只需要一个指令:

git checkout [ 版本标识 | 标签 ] <文件1>, <文件2>, ...

需要特别提醒的是,磁盘文件夹中的文件会被取出的文件「覆盖(覆盖、覆盖),因此你对该文件作出的修改会丢失。

例如,本地版本库中的文件是 80 行的,你本地的文件被你改成 100 行(但未提交),执行 git checkout 之后,你的本地文件会变成 80 行。

git-GitKraken-11

git checkout 命令就是在「翻旧账」!

HEAD 标签标注的就是你现在正在「历史长河」中的那个位置。也就是你当前看到的、「读」出来的是「哪个档」。

Last Updated:
Contributors: hemiao