Git: 记录每次更新到仓库

文件的状态:已跟踪或未跟踪。 已跟踪的状态可能处于未修改,已修改或已放入暂存区。

检查当前文件状态

要查看哪些文件处于什么状态,可以用 git status 命令,其输出十分详细,但其用语有些繁琐。 如果你使用 git status -s 命令或 git status –short 命令,你将得到一种更为紧凑的格式输出。

1
2
3
4
5
$ git status -s
?? LICENSE.txt
A lib/git.rb
M README
MM Rakefile

  • 新添加的未跟踪文件前面有 ?? 标记
  • 新添加到暂存区中的文件前面有 A 标记
  • 修改过的文件前面有 M 标记
    • M 有两个可以出现的位置,出现在右边的 M 表示该文件被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区

跟踪新文件

使用命令 git add 开始跟踪一个文件。git add 命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。

暂存已修改文件

要暂存这次更新,需要运行 git add 命令。 这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。

实际上 Git 只不过暂存了你运行 git add 命令时的版本, 如果你之后又有修改,需要重新运行 git add 把最新版本重新暂存起来。

忽略文件

一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。 来看一个实际的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 忽略所有以 .o 或 .a 结尾的文件
*.[oa]
# 忽略所有以波浪符(~)结尾的文件
*~
# no .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in the build/ directory
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory
doc/**/*.pdf

文件 .gitignore 的格式规范如下:

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

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。

  • 问号(?)只匹配一个任意字符
  • 在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)
  • 使用两个星号() 表示匹配任意中间目录,比如 `a/*/z可以匹配a/z,a/b/za/b/c/z`等。

GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,你可以在 https://github.com/github/gitignore 找到。

查看修改

要查看工作目录已经修改、但还没有暂存的修改,不加参数直接输入 git diff

要查看已暂存、将要提交的内容,可以用 git diff --staged

要查看两次提交、或再个 tag 间的不同,可以用 git diff 255de80 f3199

Git Diff 的插件版本

如果你喜欢通过图形化的方式或其它格式输出方式的话,可以使用 git difftool 命令来用 Araxis ,emerge 或 vimdiff 等软件输出 diff 分析结果。 使用 git difftool –tool-help 命令来看你的系统支持哪些 Git Diff 插件。

提交更新

git commit 命令后添加 -m 选项,将提交信息与命令放在同一行,如下所示:

1
$ git commit -m "Story 182: Fix benchmarks for speed"

跳过使用暂存区域

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

1
git commit -a -m 'added new benchmarks'

移除文件

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母),或者使用 git unstage 来撤销暂存。

另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:

1
$ git rm --cached README

git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。 比方说:

1
$ git rm log/\*.log

注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。

移动文件

要在 Git 中对文件改名,可以这么做:

1
$ git mv file_from file_to