## git diff
最后,要查看两个提交快照的绝对改动,你可以用 `git diff` 命令。 这在两个主要情况中广为使用 —— 查看两个分支彼此之间的差值,和查看自发布或者某个旧历史点之后都有啥变了。让我们看看这俩情况。
你仅需执行 `git diff [version]`(或者你给该发布打的任何标签)就可以查看自最近发布之后的改动。 例如,如果我们想要看看自 v0.9 发布之后我们的项目改变了啥,我们可以执行 `git diff v0.9`
~~~
$ git diff v0.9
diff --git a/README b/README
index d053cc8..d4173d5 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Hello World Examples
+Many Hello World Lang Examples
======================
This project has examples of hello world in
diff --git a/ruby.rb b/ruby.rb
index bb86f00..192151c 100644
--- a/ruby.rb
+++ b/ruby.rb
@@ -1,7 +1,7 @@
-class HiWorld
+class HelloWorld
def self.hello
puts "Hello World from Ruby"
end
end
-HiWorld.hello
+HelloWorld.hello
~~~
正如 `git log`,你可以给它加上 `--stat` 参数。
~~~
$ git diff v0.9 --stat
README | 2 +-
ruby.rb | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
~~~
要比较两个不同的分支,你可以执行类似 `git diff branchA branchB` 的命令。 不过它的问题在于它会完完全全按你说的作 —— 它会直接给你个补丁文件,该补丁能够将甲分支的最新快照变成乙分支的最新快照的样子。 这意味着如果两个分支已经产生分歧 —— 奔往两个不同方向了 —— 它会移除甲分支中引入的所有工作,然后累加乙分支中的所有工作。 这大概不是你要的吧 —— 你想要不在甲分支中的乙分支的改动。所以你真的需要的是两个分支叉开去时,和最新的乙分支的差别。 所以,如果我们的历史记录看起来像这样:
~~~
$ git log --graph --oneline --decorate --all
* 594f90b (HEAD, tag: v1.0, master) reverted to old class name
| * 1834130 (erlang) added haskell
| * ab5ab4c added erlang
|/
* 8d585ea Merge branch 'fix_readme'
...
~~~
并且,我们想要看“erlang”分支与主分支相比的查别。执行 `git diff master erlang` 会给我们错误的结果。
~~~
$ git diff --stat master erlang
erlang_hw.erl | 5 +++++
haskell.hs | 4 ++++
ruby.rb | 4 ++--
3 files changed, 11 insertions(+), 2 deletions(-)
~~~
你可以看到,它加上了 erlang 和 haskell 文件,这确实是我们在该分支中做的, 但是它同时恢复了我们在主分支中改动的 ruby 文件。我们真心想要的只是“erlang”分支中的改动(添加两个文件)。 我们可以通过求两个分支分歧时的共同提交与该分支的差值得到想要的结果:
~~~
$ git diff --stat 8d585ea erlang
erlang_hw.erl | 5 +++++
haskell.hs | 4 ++++
2 files changed, 9 insertions(+), 0 deletions(-)
~~~
这才是我们在找的,但是我们可不想要每次都要找出两个分支分歧时的那次提交。 幸运的是,Git 为此提供了一个快捷方式。 如果你执行 `git diff master...erlang`(在分支名之间有三个半角的点), Git 就会自动找出两个分支的共同提交(也被成为合并基础),并求差值。
~~~
$ git diff --stat master erlang
erlang_hw.erl | 5 +++++
haskell.hs | 4 ++++
ruby.rb | 4 ++--
3 files changed, 11 insertions(+), 2 deletions(-)
$ git diff --stat master...erlang
erlang_hw.erl | 5 +++++
haskell.hs | 4 ++++
2 files changed, 9 insertions(+), 0 deletions(-)
~~~
几乎每一次你要对比两个分支的时候,你都会想用三个点的语法,因为它通常会给你你想要的。
顺带提一句,你还可以让 Git 手工计算两次提交的合并基础(第一个共同的祖提交),即 `git merge-base` 命令:
~~~
$ git merge-base master erlang
8d585ea6faf99facd39b55d6f6a3b3f481ad0d3d
~~~
所以你执行下面这个也跟 `git diff master...erlang` 一样:
~~~
$ git diff --stat $(git merge-base master erlang) erlang
erlang_hw.erl | 5 +++++
haskell.hs | 4 ++++
2 files changed, 9 insertions(+), 0 deletions(-)
~~~
当然,我会推荐简单点的那个。
> **简而言之** 使用 `git diff` 查看某一分支自它偏离出来起与过去某一点之间项目的改动。 总是使用 `git diff branchA...branchB` 来查看 branchB 与 branchA 的相对差值,这会让事情简单点。