Lucius's Blog

git diff

change却未stage

常见的一种做法就是使用git diff来查看工作目录还未stage的文件差异。

实验方法:

  1. 修改一下simplegit.rb,添加一个方法

  2. 然后在README文件中添加一个作者

  3. 然后我们用git add命令把README文件载入(stage)

  4. 运行git status会显示README载入了,而simplegit.rb只是修改了还未载入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ vim lib/simplegit.rb
$ vim README
$ git add README
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: lib/simplegit.rb
#

那么,我现在想查看一下对simplegit.rb文件究竟做了什么改动?在我载入之前怎么查看这些改动的内容呢?答案是只需运行不带任何参数的git diff命令即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git diff
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..8ac6604 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -25,6 +25,10 @@ class SimpleGit
command("git log -n 25 #{treeish}")
end
+ def log_single(branch = 'master')
+ command("git log --pretty=oneline #{branch}")
+ end
+
def blame(path)
command("git blame #{path}")
end

这样就可以看到我添加到文件中的内容,现在我可以决定是不是要将其载入了。注意,README文件的修改并没有显示出来。

stage但未commit

为了查看载入(staged)而并未提交(not committed)的内容差异,可以使用git diff --stage命令(在git 1.6之前的版本中,使用--cached

1
2
3
4
5
6
7
8
9
10
$ git diff --staged
diff --git a/README b/README
index c526f88..879f0d4 100644
--- a/README
+++ b/README
@@ -8,3 +8,4 @@ It is an example for the Git Peepcode book that I'm currently writin
Author : Scott Chacon (schacon@gmail.com)
Orange Peel Chacon (opchacon@gmail.com)
Magnus O. Chacon (mchacon@gmail.com)
+ Josephine Chacon (jo.chacon@gmail.com)

适应情形:在运行git commit(不带'-a')之前,查看所有载入而未提交的变更内容。

最后一次提交之后的所有变更

现在,如果你想查看最后一次提交之后工作目录中文件的变更,你可以在git diff之后加一个HEAD来进行比对:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ git diff HEAD
diff --git a/README b/README
index c526f88..879f0d4 100644
--- a/README
+++ b/README
@@ -8,3 +8,4 @@ It is an example for the Git Peepcode book that I'm currently writin
Author : Scott Chacon (schacon@gmail.com)
Orange Peel Chacon (opchacon@gmail.com)
Magnus O. Chacon (mchacon@gmail.com)
+ Josephine Chacon (jo.chacon@gmail.com)
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..8ac6604 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -25,6 +25,10 @@ class SimpleGit
command("git log -n 25 #{treeish}")
end
+ def log_single(branch = 'master')
+ command("git log --pretty=oneline #{branch}")
+ end
+
def blame(path)
command("git blame #{path}")
end

适用情形:在运行git commit -a之前。显示所有载入的和未载入的变更。

从一个特定点开始文件的修改情况

这也是最常见的一个问题。譬如,如何查看创建v1.6这个标签之后README文件所发生的修改呢,可以这样:

1
2
3
4
5
6
7
8
9
10
11
12
$ git diff v1.6.0 -- README 
diff --git a/README b/README
index 548142c..5fa41b7 100644
--- a/README
+++ b/README
@@ -24,7 +24,7 @@ It was originally written by Linus Torvalds with help of a group o
hackers around the net. It is currently maintained by Junio C Hamano.
Please read the file INSTALL for installation instructions.
-See Documentation/tutorial.txt to get started, then see
+See Documentation/gittutorial.txt to get started, then see
Documentation/everyday.txt for a useful minimum set of commands,
and "man git-commandname" for documentation of each command.

上面就显示出了工作目录中README文件的版本差异–如果你做了本地修改,载入或未载入,都会在这次比对中显示出来。

两次提交的差异比对

如果你想对两次快照做差异比对,也即项目的两个版本之间比对–直接在git diff后跟上要比对的两个版本号即可:

1
$ git diff v1.0 v1.1

diff命令加这样的参数,显示某些统计数,下面是显示v1.6.1.1和v1.6.1.2两个版本之间差异的统计数字:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ git diff v1.6.1.1 v1.6.1.2 --stat
Documentation/RelNotes-1.6.1.2.txt | 39 +++++++++++++
Documentation/config.txt | 4 +-
Documentation/git-ls-tree.txt | 8 +++-
GIT-VERSION-GEN | 2 +-
RelNotes | 2 +-
builtin-commit.c | 6 ++
builtin-gc.c | 8 ++-
builtin-grep.c | 15 +++++-
builtin-log.c | 28 +++++++++-
builtin-ls-tree.c | 7 ++-
builtin-send-pack.c | 43 +++++++--------
diffcore-rename.c | 9 +++-
git-sh-setup.sh | 2 +-
sha1_file.c | 3 +-
sha1_name.c | 2 +-
t/t2300-cd-to-toplevel.sh | 4 +-
t/t4014-format-patch.sh | 52 +++++++++++++++++-
t/t5519-push-alternates.sh | 106 ++++++++++++++++++++++++++++++++++++
t/t7002-grep.sh | 7 +++
test-path-utils.c | 2 +-
20 files changed, 306 insertions(+), 43 deletions(-)

还可以深入查看某个具体文件的变更比对:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git diff v1.6.1.1 v1.6.1.2 -- sha1_file.c
diff --git a/sha1_file.c b/sha1_file.c
index 52d1ead..ce5ea12 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2337,7 +2337,8 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const c
static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
void *buf, unsigned long len, time_t mtime)
{
- int fd, size, ret;
+ int fd, ret;
+ size_t size;
unsigned char *compressed;
z_stream stream;
char *filename;

执行之后会显示sha1_file.c文件在v1.6.1.1和v1.6.1.2两个版本之间的比对结果。

在合并某分支前查看变更内容

这是个比较奇怪的问题,因为如果你开始是工作在一个主分支上,而后生成了两个分支,如果直接对比快照的话,结果只会显示从一个状态到另一个状态的差异比对结果。
举例来说,如果你创建了一个dev的分支,进入这个分支给lib/simplegit.rb添加了一个函数,然后回到了master分支,删除了README文件的一行,然后运行:

1
$ git diff master dev

结果会显示你给某个文件中添加了方法,还往README文件添加了一行内容。为什么会这样?因为对dev分支来说,README文件还是原样,而在’master’上,你已经删掉了一行,这样直接对两个快照进行对比就好似’dev’分支添加了一行进去一样。你想查看的实际上是在创建dev分支之后在这条分支上的差异对比,所以应该执行这样的命令:

1
$ git diff master...dev

这就不会拿master分支上最后一个快照和dev分支上最后一个快照进行比对–而是用dev与master所交的那个分歧点和现在的dev分支上最后一个快照进行比对。在我们这个例子中,这样比对的结果是显示对那个文件添加了一个函数。如果你目前正处在master分支上,你可以运行:

1
$ git diff ...dev

跟上面的结果是一样的。所以,如果你想查看将要合并的某个分支会有什么样的变化,可以执行:

1
$ git diff ...(branch)

将branch替换为你想要合并的分支名即可。

我只是试下能不能被赞赏😳