Git流程和核心语法,与svn对比(二)
此前已讨论过Git的安装、配置和clone,详情浏览一下文章,本文讨论Git的更新提交,查看历史和撤销等操作。
Git流程和核心语法,与svn对比(一):http://www.jianshu.com/p/d930f2918ef6
工作目录下的每一个文件都不外乎两种状态:** 已跟踪或未跟踪** 。已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。 工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。 初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。
编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。 我们逐步将这些修改过的文件放入暂存区,然后提交所有暂存了的修改,如此反复。工作中的修改,提交亦是这个过程,文件的状态周期如下:

说了这么多,下面直接说语法:
1.检查当前文件状态
要查看哪些文件处于什么状态,可以用 git status 命令。这里假如有一个跟踪文件REDAME.md被修改,一个未跟踪文件COMMENT被添加。使用 git status命令,会有如下输出:
$ git status
On branch master
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
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: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
COMMENT
no changes added to commit (use "git add" and/or "git commit -a")
由于REDAME.md文件是被跟踪的,所以出现在Changes not staged for commit:已修改未提交下面;COMMENT文件是为被跟踪的,出现在Untracked files:未跟踪文件下面。
这里出现了问题,已修改的被跟踪文件怎么添加到已暂存状态;未跟踪文件怎么修改为被跟踪文件。
2.添加到已暂存状态和添加为被跟踪文件。
由1问题引出的更改命令:git add 。这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。
1)将已修改的文件REDAME.md添加到已暂存:
$ git add README.md
$ git status
On branch master
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
COMMENT
现在README.md已变成Changes to be committed:已暂存状态,随时准备提交。
2)未跟踪文件COMMENT修改为被跟踪文件:
$ git add COMMENT
$ git status
On branch master
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: COMMENT
modified: README.md
现在COMMENT状态已变为跟踪文件,且是已暂存状态,等待提交。
** tips:git status 命令的输出十分详细,但其用语有些繁琐。 如果你使用 git status -s 命令或 git status --short 命令,你将得到一种更为紧凑的格式输出**
$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
新添加的未跟踪文件前面有 ?? 标记,新添加到暂存区中的文件前面有 A 标记,修改过的文件前面有 M 标记。 你可能注意到了 M 有两个可以出现的位置,出现在右边的 M 表示该文件被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区。 例如,上面的状态报告显示: README 文件在工作区被修改了但是还没有将修改后的文件放入暂存区,lib/simplegit.rb 文件被修改了并将修改后的文件放入了暂存区。 而 Rakefile 在工作区被修改并提交到暂存区后又在工作区中被修改了,所以在暂存区和工作区都有该文件被修改了的记录。
3.忽略处理
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。 来看一个实际的例子:
$ cat .gitignore
*.[oa]
*~
cat为关联,联系之意,即git关联.gitignore文件。第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。第二行告诉 Git 忽略所有以波浪符(~)结尾的文件。 要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件,更多文件 .gitignore 的格式规范见Git2.2章。
4.提交更新
在此之前,请一定要确认还有什么修改过的或新建的文件还没有 git add 过,否则提交的时候不会记录这些还没暂存起来的变化。 这些修改过的文件只保留在本地磁盘。 所以,每次准备提交前,先用 **git status **看下,是不是都已暂存起来了, 然后再运行提交命令 git commit:
$ git commit
这种方式会启动文本编辑器以便输入本次提交的说明。 (默认会启用 shell 的环境变量 $EDITOR所指定的软件,一般都是 vim 或 emacs。当然也可以按照 起步 介绍的方式,使用 git config --global core.editor命令设定你喜欢的编辑软件。)
编辑器会显示类似下面的文本信息(本例选用 Vim 的屏显方式展示):
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# new file: README
# modified: CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C
可以看到有这次提交的修改和添加的文件,另外开头还有一空行,供你输入提交说明,退出编辑器时,Git 会丢掉注释行,用你输入提交附带信息生成一次提交。
1)另外,你也可以在 commit 命令后添加 -m 选项,将提交信息与命令放在同一行,如下所示:
$ git commit -m " liitte change"
[master ded166c] liitte change
2 files changed, 1 insertion(+), 1 deletion(-)
create mode 100644 COMMENT
提交后它会告诉你,当前是在哪个分支(master)提交的,本次提交的完整 SHA-1 校验和是什么(463dc4f),以及在本次提交中,有多少文件修订过,多少行添加和删改过
2)跳过使用暂存区域直接提交
Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:
$ 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: CONTRIBUTING.md
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks
1 file changed, 5 insertions(+), 0 deletions(-)
5.移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 **git rm **命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: PROJECTS.md
另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 **--cached **选项:
$ git rm --cached README
6.移动文件
**git mv **:git中即改名操作, 要在 Git 中对文件改名,可以这么做:
$ git mv file_from file_to
其实,运行 git mv 就相当于运行了下面三条命令:
$ mv README.md README
$ git rm README.md
$ git add README
Git 会意识到这是一次改名,所以不管何种方式结果都一样。 两者唯一的区别是,mv 是一条命令而另一种方式需要三条命令,直接用 git mv 轻便得多。 不过有时候用其他工具批处理改名的话,要记得在提交前删除老的文件名,再添加新的文件名。
7.查看提交历史
git log命令可以查看提交历史:
$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
默认不用任何参数的话,git log会按提交时间列出所有的更新,最近的更新排在最上面。正如你所看到的,这个命令会列出每个提交的SHA-1校验和,作者的名字和电子邮件地址,提交时间以及提交说明。
git log 有许多选项可以帮助你搜寻你所要找的提交,接下来我们介绍些最常用的。
1)-p用来显示每次提交的内容差异。你也可以加上-2来只显示最近两次提交。
2)--stat选项 ,看到每次提交的简略的统计信息。
log还有很多其他选项可以设置,如历史提交格式,指定时间节点之后的log等,具体细节见Git书2.3章。
8. 撤消操作
1)
有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令尝试重新提交:
$ git commit --amend
这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。举个例子:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最终你只会有一个提交 -,第二次提交将代替第一次提交的结果,查看log只会有第二次记录。
暂到此。