现在我们的机器上有了一个 真实项目 的 Git 仓库,并从这个仓库中检出了所有文件的 工作副本。 通常,我们会对这些文件做些修改,每当完成了一个阶段的目标,想要将记录下它时,就将它提交到仓库。请记住,我们工作目录下的每一个文件都不外乎这两种状态:已跟踪 或 未跟踪。
1 检查当前文件状态
查看哪些文件处于什么状态,使用git status
:
$ git status
如果在克隆仓库后立即使用此命令:
出现的"On branch … clean"信息说明我们现在的工作目录相当干净。换句话说,所有已跟踪文件在上次提交后都未被更改过。 此外,上面的信息还表明,当前目录下没有出现任何处于未跟踪状态的新文件,否则 Git 会在这里列出来。 最后,该命令还显示了当前所在分支,并告诉我们这个分支同远程服务器上对应的分支没有偏离。 现在,分支名是“master”,这是默认的分支名。
现在在项目下创建一个新的 README
文件:
$ echo 'My Project' > README
$ git status
在状态报告中可以看到新建的 README
文件出现在 Untracked files
下面。 未跟踪的文件意味着 Git 在之前的快照(提交)中没有这些文件;Git 不会自动将之纳入跟踪范围,除非我们明明白白地告诉它“我需要跟踪该文件”。不过现在我们需要跟踪管理README
这个文件。
2 跟踪新文件
使用git add
开始跟踪一个文件并用git status
查看状态。所以,要跟踪README文件,运行:
$ git add README
$ git status
只要在 Changes to be committed
这行下面的,就说明是已暂存状态。 如果此时提交,那么该文件在我们运行 git add
时的版本将被留存在后续的历史记录中。
3 暂存已修改的文件
现在我们来修改一个已被跟踪的文件。比如,该项目下的README.md
文件(这是一个已被跟踪的文件)。运行:
$ git status
文件 README.md
出现在 Changes not staged for commit
这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。 要暂存这次更新,需要运行 git add
命令。
git add 命令功能:
- 跟踪新文件
- 把已跟踪的文件放到暂存区
- 用于合并时把有冲突的文件标记为已解决状态
$ git add README.md
$ git status
现在两个文件都已暂存,下次提交时就会一并记录到仓库。 假设此时,我们想要在 README.md
里再加条注释。 重新编辑存盘后,准备好提交。 不过且慢,再运行 git status
看看:
$ vim README.md
$ git status
怎么回事? 现在 README.md
文件同时出现在暂存区和非暂存区。 这怎么可能呢? 好吧,实际上 Git 只不过暂存了你运行 git add
命令时的版本。 如果我们现在提交,README.md
的版本是我们最后一次运行 git add
命令时的那个版本,而不是我们运行 git commit
时,在工作目录中的当前版本。 所以,运行了 git add
之后又作了修订的文件,需要重新运行 git add
把最新版本重新暂存起来:
$ git add README.md
$ git status
4 状态简览
git status
命令的输出十分详细,但其用语有些繁琐。 Git 有一个选项可以帮你缩短状态命令的输出,这样可以以简洁的方式查看更改:
$ git status -s
$ git status -short
??
:新添加的未跟踪文件A
:新添加到暂存区中的文件M
:修改过的文件
5 忽略文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore
的文件,列出要忽略的文件的模式。 来看一个实际的 .gitignore
例子:
$ cat .gitignore
*.[oa] # 告诉Git忽略所有以 .o 或 .a 结尾的文件
*~ # 告诉 Git 忽略所有名字以波浪符(~)结尾的文件
要养成一开始就为我们的新仓库设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
文件.gitignore
的格式规范如下:
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
- 匹配模式可以以(
/
)开头防止递归。 - 匹配模式可以以(
/
)结尾指定目录。 - 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(
!
)取反。
6 查看已暂存和未暂存的修改
git diff
可以通过文件补丁的格式更加具体地显示哪些行发生了改变,可以用来回答:
- 当前做的哪些更新尚未暂存?
- 有哪些更新已暂存并准备好下次提交?
假如再次修改 NEWFILE 文件后暂存,然后编辑 README.md
文件后先不暂存, 运行 status
命令将会看到:
运行git diff
,观察暂存前后的变化:
$ git diff
然后用 git diff --cached
查看已经暂存起来的变化( --staged
和 --cached
是同义词):
$ git diff --cached
7 提交更新
现在的暂存区已经准备就绪,可以提交了。 在此之前,请务必确认还有什么已修改或新建的文件还没有 git add
过, 否则提交的时候不会记录这些尚未暂存的变化。 这些已修改但未暂存的文件只会保留在本地磁盘。 所以,每次准备提交前,先用 git status
看下,我们所需要的文件是不是都已暂存起来了, 然后再运行提交命令 git commit
:
$ git commit
$ git commit -m "提交说明"
8 跳过使用暂存区域
尽管使用暂存区域的方式可以精心准备要提交的细节,但有时候这么做略显繁琐。 Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit
加上 -a
选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add
步骤:
$ git status
$ git commit -a -m '提交说明'
9 移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm
命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
情况一:从工作目录中手工删除文件
运行 git status
时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单)看到:
$ rm <filename>
$ git status
再运行 git rm
记录此次移除文件的操作:
$ git rm <filename>
$ git status
下一次提交时,该文件就不再纳入版本管理了。
如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f
。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。
情况二:把文件从 Git 仓库中删除,但保留在当前工作目录中
即想让文件保留在磁盘,但是并不想让 Git 继续跟踪。
当我们忘记添加 .gitignore
文件,不小心把一个很大的日志文件或一堆 .a
这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached
选项:
$ git rm --cached README
10 移动文件
不像其它的 VCS 系统,Git 并不显式跟踪文件移动操作。 如果在 Git 中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次改名操作。
在Git中对文件改名:
$ git mv file_from file_to
举例:
$ git mv README.md README
$ git status
运行 git mv
就相当于运行了下面三条命令:
$ mv README.md README
$ git rm README.md
$ git add README