推荐安装 p4merge 作为 git 的 diff 工具:
# Starts git difftool for all modified files
git difftool
# Compare only specific file
git difftool location\filename
# diff 当前版本的文件和某个commit的某个文件
git difftool 3693493981a35c07f2bee7cae71f8e8bd95be625 -- filename
# git difftool [start commit]..[end commit] filename
git log filename # 查看某个文件的提交记录
git difftool 6cde26245763dd43f9505c7578a1f7be44b7fad1..8d5336398 -- filename
常用 example:
git diff
:是查看 workspace 与 index 的差别的。
git diff --cached
:是查看 index 与 local repositorty 的差别的。
git diff HEAD
:是查看 workspace 和 local repository 的差别的。(HEAD 指向的是 local repository 中最新提交的版本)
注:git diff 后跟两个参数,如果只写一个参数,表示默认跟 workspace中的代码作比较。git diff 显示的结果为 第二个参数所指的代码在第一个参数所指代码基础上的修改。如,git diff HEAD
表示 workspace 在 最新commit的基础上所做的修改。
如图:
在git提交环节,存在三大部分:workspace, index, repository 尊重作者,原文链接
这三大部分中:
workspace:就是你所工作在的目录,每当你在代码中进行了修改,working tree的状态就改变了。
index:是索引文件,它是连接working tree和commit的桥梁,每当·我们使用git-add命令来登记后,index file的内容就改变了,此时index file就和working tree同步了。
repository:是最后的阶段,只有commit了,我们的代码才真正进入了git仓库。我们使用git commit -m "xxx"
就是将 index 里的内容提交到本地仓库中(push 之后就到了远程仓库了)。
要跟历史版本中的代码作比较:
git diff HEAD^
比较 workspace 与最新commit的前一次commit的差异(注意与git diff HEAD的差别)
git diff HEAD~2
比较 workspace 与上2次提交的差异,相当于 git diff HEAD~2 HEAD~0
,注意两个HEAD的位置,diff显示的结果表示 后一个(HEAD~0) 相对于 前一个的修改(HEAD~2)
当然也可以通过 a/b 来区分对应的文件,如下:
--- a/build/test.cmake (a表示 git diff后的第一个文件,---表示删除)
+++ b/build/test.cmake (b表示 git diff后的第二个文件,+++表示增加)
例如,git diff HEAD~2 HEAD^
比较上次commit(即最新的commit的前一次)与上上次commit之间的差异,HEAD^=HEAD^1=HEAD~1
;其中 a
表示 HEAD~2
, b
表示 HEAD^
。
注意
^
与~
之间的区别,当存在多个分支时,^
可以用来选择分支,HEAD~i
永远只选择第i
级父节点的第一个分支,HEAD~i^2
选择第i
级父节点的第二个分支,以此类推;HEAD^=HEAD^1=HEAD~1
;如果没有分支,只有一条主线,则HEAD^^^=HEAD^1^1^1=HEAD~3
,如果该级几点有第二个分支,则表示为:HEAD^^^2 = HEAD~2^2
.
图文可见链接
为了更加清晰的阐释这个关系,来给出一个实例:
[yaya@yaya-desktop]$ cat main.c
#include<stdio.h>
int main(int argc,char *argv[])
{
printf(“hello.\n”);
printf(“he was a student.\n”);
return 0;
}
然后git init
, git add .
, git commit
;
之后你将源代码修改为:
[yaya@yaya-desktop]$ cat main.c
#include<stdio.h>
int main(int argc,char *argv[])
{
printf(“hello.\n”);
printf(“he was a student.\n”);
printf(“he was born in finland.\n”);
return 0;
}
此时你git add .
,但不用执行git commit
命令。然后你再将源代码改为:
[yaya@yaya-desktop]$ cat main.c
#include<stdio.h>
int main(int argc,char *argv[])
{
printf(“hello.\n”);
printf(“he was a student.\n”);
printf(“he was born in finland.\n”);
printf(“he is very clever!\n”);
return 0;
}
这个时候,你执行如下三个命令,仔细查看,我相信你会发现它们三个的区别的!
$ git diff
$ git diff –cached
$ git diff HEAD
讲到这里,基本上对git diff
命令有了比较深入的了解了,现在你再使用git status
看看输出结果,样子大概是这样:
[yaya@yaya-desktop]$ git status
# On branch master
# Changes to be committed:
# (use “git reset HEAD <file>…” to unstage)
#
# modified: main.c
#
# Changed but not updated:
# (use “git add <file>…” to update what will be committed)
#
# modified: main.c
很明显可以知道:
Changes to be committed表示已经存在于index file里,但尚未提交。
Changed but not updated表示在working tree已经做修改,但还没有使用git add登记到index file里。