git-command

配置并初始化一个仓库(repository)
开始或听着跟踪(track)文件
暂存(stage)或提交(commit)更改
配置Git来忽略指定的文件和文件模式
撤销错误操作
浏览历史版本以及不同提交间的差异
向远程仓库推送(push)
从远程仓库拉取(pull)文件

创建版本库

创建目录mygit

1
$ mkdir mygit

进入mygit

1
$ cd mygit

仓库初始化

1
$ git init

Windows 系统下,通过Git Bash 操作如下:

Mac 下,通过 Terminal 操作如下:

当执行完git init 命令后,可以看到控制台多出了(master)的标识,
它表示当前是在master分支,这也是 Git 为我们创建的默认分支(后面会详细介绍 Git 分支)。

使用ls -al 命令查看git init 命令为我们生成了哪些隐藏文件

1
$ ls -al

可以看到,mygit 目录下多出了.git 目录,这个子目录包含初始化的 Git 仓库所有必须的文件,
比如有我们在上一篇文章中介绍的关于git config –local配置方式中提到的config文件。

一般我们不会直接修改这个文件,而是通过Git 提供的命令去操作。

查看工作目录状态

1
$ git status

git status 命令将会成为以后经常会使用的命令,用来查看工作目录文件的状态,以便决定下一步的操作。

现在我们可以创建一个文件,然后使用git add 命令来实现对文件对追踪。

1
$ touch hello.txt

编辑文件,添加如下内容

1
vi hello.txt

1
hello Git

查看工作目录状态

1
git status

在状态报告中可以看到,当前在 master 分支,hello.txt 文件未被跟踪,
我们可以使用 git add 命令来实现对文件的跟踪。

开始跟踪hello.txt文件

1
$ git add hello.txt

控制台没有任何信息输出(Linux/Unix系统的设计思想:没有消息就是最好的消息)
也可以使用git add . 命令对当前目录下所有文件进行跟踪。

查看状态

1
$ git status

可以看到,hello.txt文件已被跟踪,并处于暂存状态,只要在Changes to be committed:这行下面的,就说明是已暂存状态。
对于已暂存的文件,我们可以将hello.txt文件从暂存区回退到工作区,也可以提交hello.txt文件。

这里我们先演示从暂存区回退到工作区

1
$ git rm --cached hello.txt

查看状态,发现和刚创建完文件时一样。

接下来,我们重新将hello.txt 文件添加到暂存区

1
$ git add hello.txt

提交到版本库

1
$ git commit

输入git commit直接回车,默认会调用本机文本编辑器,需要输入提交信息,我们输入commit hello.txt信息,保存,关闭文件。

Windows 系统下,通过Git Bash 操作如下:

Mac 下,通过 Terminal 操作如下:

此时,hello.txt文件已成功提交,可以看到如下信息:

一般情况下,我们输入的提交信息都不会特别多,这时我们可以使用 git commit -m "提交信息"

查看工作区状态

1
2
3
$ git status
On branch master
nothing to commit, working tree clean

说明现在的工作目录很干净。换句话说,就是当前目录下没有出现任何未跟踪状态的新文件,
并且所有已跟踪文件在上次提交后都没有被修改过,否则Git 会在这里列出来。

查看提交日志

1
$ git log

默认不加任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面。
git log 命令会列出每个提交的SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。

暂存修改的文件

修改hello.txt 文件

1
$ vi hello.txt

内容如下:

1
2
hello Git
hello Java

出现在Changes not staged for commit 这行下面,说明修改了已跟踪的文件,但还没有放到暂存区。
要暂存这次更新,需要运行git add命令。或者使用git checkout 命令将工作区的文件撤销修改。
git add 是个多功能的命令:

  • 用于开始跟踪新文件;
  • 把已跟踪的文件放到暂存区;
  • 用于把有冲突的文件标记为已解决状态(这个后面会用到)。

我们先演示下使用git checkout 命令撤销修改

1
git checkout -- hello.txt

可以看到hello.txt文件中添加的一行文本(hello Java)被撤销。

我们按照上面的方式再修改hello.txt文件,演示将修改添加到暂存取的功能
运行git add 命令将已修改的hello.txt 文件放到暂存区

1
$ git add hello.txt

通过git status 可以看到hello.txt文件的修改已暂存。

状态简览

git status 命令的输出十分详细,使用 git status -sgit status --short 命令可以得到更为紧凑的格式输出。

1
git status -s

新添加的未跟踪文件前面有 ?? 标记

新添加到暂存区的文件前面有 A 标记

修改过的文件前面有 M 标记,注意M有两个可以出现的位置,
出现在右边的M表示该文件被修改了但还没有放到暂存区,出现在左边的 M 表示该文件被修改并放入了暂存区。

查看已暂存和未暂存的修改

1
git diff

git diff 不加任何参数比较工作目录中的当前文件和暂存区之间的差异
git diff HEAD 比较工作区与最新本地版本库
git diff commit-id 比较工作区与指定 commit-id 之间的差异

git diff –cached 比较暂存区与最新本地版本库
git diff –cached commit-id 比较暂存区与指定commit-id 之间差异

提交时跳过使用暂存区

git commit 使用暂存区可以精心准备要提交的内容,但有时候这么做略显繁琐。Git提供了一个跳过使用暂存区的方式,
在提交的时候给git commit 加上-a 选项,Git会自动把所有已跟踪过的文件暂存起来一并提交。

1
git commit -am '提交说明'

移除文件

要从Git中移除某个文件,就必须要从已跟踪文件清单中移除,然后提交。

1
2
git rm hello.txt
git commit -m '提交说明'

大部分情况下,我们会直接在文件管理器中把文件删除了或者使用rm 命令删除

1
$ rm hello.txt

1
$ git status

有两个选择:
1.确实要从版本库中删除该文件,就用git rm 记录此次删除文件的操作,并用git commit。

1
2
git rm hello.txt
git commit -m '提交说明'

现在文件就从版本库中删除了。

2.删错了,把误删的文件恢复到最新版本。

1
git checkout -- hello.txt

用版本库里的版本替换工作区的版本,可能会丢失最近一次提交后你修改的内容。

想把文件从Git仓库中删除,但是仍希望保留到当前工作目录中,
git rm –cached hello.txt

重命名文件

在我们日常开发中,可能会出现修改文件名的情况,比如觉得某个类的名字取的不能够见名知义,想要修改。
要在Git 中对文件重命名,可以使用git mv 命令

1
$ git mv file_from file_to

比如,我们将文件 hello.txt 改名为hello2.txt

1
$ git mv hello.txt hello2.txt

查看状态信息,可以看到 Git 能够识别到我们对文件执行了重命名操作,并且已是暂存状态。
运行git mv 相当与运行了下面三条命令:

1
2
3
$ mv hello.txt hello2.txt
$ git rm hello.txt
$ git add hello2.txt

重命名已完成,这个时候我们可以提交修改 git commit -m "重命名文件"
或者误操作了这个文件,想要回退。

1
$ git reset HEAD hello2.txt

这样hello2.txt 文件处于未跟踪状态了。

1
$ git reset HEAD hello.txt
1
2
$ git checkout -- hello.txt
$ rm hello2.txt

文件撤销

在日常开发的过程中,我们可能会遇到以下几种的场景:
场景一:
在工作区修改了文件内容,还没添加到暂存区,发现修改错了想要撤销修改。

1
2
$ cat hello.txt
hello Git

修改hello.txt 文件,添加一行内容hello world

1
2
3
$ vim hello.txt
hello Git
hello world

1
2
3
4
5
6
7
8
9
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: hello.txt

no changes added to commit (use "git add" and/or "git commit -a")

使用git checkout -- <file>... 撤销修改

1
$ git checkout -- hello.txt

查看状态

1
2
3
$ git status
On branch master
nothing to commit, working tree clean

查看hello.txt 文件内容

1
2
$ cat hello.txt
hello Git

hello.txt 文件回到和版本库一样。

场景二:
与场景一一样在工作区修改了文件内容,不同的是这个时候被修改的 hello.txt 文件已经添加到暂存区了,需要撤销修改。

1
2
3
$ vim hello.txt
hello Git
hello world

查看状态

1
2
3
4
5
6
7
8
9
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: hello.txt

no changes added to commit (use "git add" and/or "git commit -a")

将修改的文件添加到暂存区

1
$ git add hello.txt

查看状态

1
2
3
4
5
6
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: hello.txt

现在我们首先将文件从暂存区回退到工作区

1
2
3
$ git reset HEAD hello.txt
Unstaged changes after reset:
M hello.txt

查看状态,此时和场景一的状态是一样的了。

1
2
3
4
5
6
7
8
9
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: hello.txt

no changes added to commit (use "git add" and/or "git commit -a")

使用git checkout -- <file>... 撤销修改

1
$ git checkout -- hello.txt

场景三:
与场景二一样在工作区修改了文件内容,被修改的 hello.txt 文件已经添加到暂存区了,这个时候在工作区又做了修改,需要撤销本次修改。

1
2
3
$ vim hello.txt 
hello Git
hello world

将修改的文件添加到暂存区

1
$ git add hello.txt

再次编辑文件,添加新的一行内容hello Java

1
2
3
4
$ vim hello.txt 
hello Git
hello world
hello Java

查看状态

1
2
3
4
5
6
7
8
9
10
11
12
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: hello.txt

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: hello.txt

此时,hello.txt 文件同时出现在暂存区和非暂存区。
我们想要撤销本次的修改,那么只要执行git checkout -- hello.txt 就可以了。

1
2
$ git checkout hello.txt
Updated 1 path from the index

1
2
3
4
5
6
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: hello.txt

查看文件内容,本次修改已经撤销了。

1
2
3
$ cat hello.txt
hello Git
hello world

文件撤销小结

如果hello.txt 修改后,还没有添加到暂存区,现在想要撤销,执行git checkout -- hello.txt 则回到和版本库一样的状态。
如果hello.txt 已经添加到暂存区,又做了修改,现在想要撤销本次修改,执行git checkout -- hello.txt ,撤销的是工作目录的修改,则回到和暂存区一样的状态。
当然如果是一个新的文件还没有添加到暂存区,也就没有Git撤销操作了。总之,就是让这个文件回到最近一次git commit或git add时的状态。

场景四:
这个时候终于把hello.txt 文件修改完了,愉快的执行了提交。

1
2
3
$ git commit -m "fix bug #666"
[master 50b27fc] fix bug #666
1 file changed, 1 insertion(+)

提交完后发现bug号写错了,其实修改的是bug #66,想要修改提交说明。

查看提交说明

1
2
3
4
5
6
7
$ git log

commit 50b27fce9b19dd25736893bcc3bb49c46a1242ae (HEAD -> master)
Author: geekymv <[email protected]>
Date: Thu Jun 13 19:22:14 2019 +0800

fix bug #666

修改最近一次的提交说明

1
2
3
4
5
$ git commit --amend -m "fix bug #66"

[master 5c10da1] fix bug #66
Date: Thu Jun 13 19:22:14 2019 +0800
1 file changed, 1 insertion(+)

1
2
3
4
5
6
7
$ git log

commit 5c10da1d45b53cf2f98c538b9f8d758ff961fd81 (HEAD -> master)
Author: geekymv <[email protected]>
Date: Thu Jun 13 19:22:14 2019 +0800

fix bug #66

已经成功修改了提交说明,并没有新增commit id。

版本回退

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ git log
commit 5c10da1d45b53cf2f98c538b9f8d758ff961fd81 (HEAD -> master)
Author: geekymv <[email protected]>
Date: Thu Jun 13 19:22:14 2019 +0800

fix bug #66

commit 29cf508b469fd4b89de66b8b979e14b10c2663ea
Author: geekymv <[email protected]>
Date: Thu Jun 13 18:55:47 2019 +0800

修改文件

commit 0a49afaf82d809568ecc942baf4c170d5027ef6d
Author: geekymv <[email protected]>
Date: Wed Jun 5 21:03:17 2019 +0800

add

git log 命令显示从最近到最远的提交说明,如果觉得输出的信息太多,可以加上参数--pretty=oneline

1
2
3
4
$ git log --pretty=oneline
5c10da1d45b53cf2f98c538b9f8d758ff961fd81 (HEAD -> master) fix bug #66
29cf508b469fd4b89de66b8b979e14b10c2663ea 修改文件
0a49afaf82d809568ecc942baf4c170d5027ef6d add

这下清爽多了!

在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^
当然往上10个版本写10个^比较容易数不过来,所以写成HEAD~10。

1
2
$ git reset --hard HEAD^
HEAD is now at 29cf508 修改文件

1
2
3
$ git log --pretty=oneline
29cf508b469fd4b89de66b8b979e14b10c2663ea (HEAD -> master) 修改文件
0a49afaf82d809568ecc942baf4c170d5027ef6d add

可以看到当前版本是29cf50...

现在要想还回到指定回到5c10da1d45b53cf2f98c538b9f8d758ff961fd81版本,
当然版本号没必要写全,前几位就可以了,Git会自动去找。

1
2
$ git reset --hard 5c10da
HEAD is now at 5c10da1 fix bug #66

可以看到又回到了5c10da...版本

1
2
3
4
$ git log --pretty=oneline
5c10da1d45b53cf2f98c538b9f8d758ff961fd81 (HEAD -> master) fix bug #66
29cf508b469fd4b89de66b8b979e14b10c2663ea 修改文件
0a49afaf82d809568ecc942baf4c170d5027ef6d add

当你用$ git reset --hard HEAD^命令回退到29cf50...版本时,再想恢复到最新版本怎么版呢?
上面我们能恢复是因为我们在笔记中记录了 commit id。这个时候使用git log 已经看不到最新版本到commit id 了。
不用担心,在Git中总是有后悔药可以吃,git reflog记录你的每一次命令。

1
2
3
4
5
6
$ git reflog
29cf508 (HEAD -> master) HEAD@{0}: reset: moving to 29cf
5c10da1 HEAD@{1}: reset: moving to 5c10da1d45b53cf2f98c538b9f8d758ff961fd81
29cf508 (HEAD -> master) HEAD@{2}: reset: moving to HEAD^
5c10da1 HEAD@{3}: commit (amend): fix bug #66
50b27fc HEAD@{4}: commit: fix bug #666

坚持原创技术分享,您的支持将鼓励我继续创作!