Git-diff命令

Git diff命令

Git diff命令的作用

diff命令的只有一句话:

git-diff - Show changes between commits, commit and working tree, etc

翻译一下就是git-diff—显示提交、提交和工作树等之间的更改。

是不是还是不懂?那就对了,直接看Git手册就能学会Git的,那是人干的事儿吗?手册是被浓缩后的内容,它肯定是对的,但绝对称不上友好,而我现在正在做的事情就是把它精简掉的那些东西再翻出来,让人可以与之友好的对话。

diff命令就是比较内容,那么到底那些内容需要比较呢?让那个我们来好好的捋一捋:

  • Git有Work区,里面无疑就是普通的文件和目录了
  • Git有Stage区,里面是Git处理过的暂存的文件(Blob)和目录(tree),也可以把它理解为一个暂存的版本
  • Git有Commit区,里面就是各个提交的版本了
  • Git还可以指定tag,它就相当于一个别名

没错,这些都是可以比较。

测试工程

为了测试git diff命令,我们需要搭建一个特别设计的git工程,它是下面的样子:

在这里插入图片描述

简要说明一下这张图:

  • 最下面的紫色方块代表工作区
  • 工作区上面的绿色方块代表暂存区
  • 上面的各个圆圈代码commit
  • 蓝色的飘带标记代表命名的tag,这里有a,b,c三个tag
  • 黄色的飘带标记代表分支,这里有master,yes和no三个分支

为简单起见,我们处理一个文件readme.txt

要构造这样的git工程并不是一件很困难的事情。

首先要创建工程:

git init

然后做第一次提交,并打上tag:

# commit ver-a
echo a > readme.txt

git add .
git commit -m 'ver-a'
git tag a

同理,提交b和c:

# commit ver-b
echo b > readme.txt

git add .
git commit -m 'ver-b'
git tag b

# commit ver-c
echo c > readme.txt

git add .
git commit -m 'ver-c'
git tag c

在这里创建分支yes

git checkout -b yes

为yes分支做两次提交:

# commit ver-y1
echo -e 'y\n1' > readme.txt

git add .
git commit -m 'ver-yes1'

# commit ver-yes2
echo -e 'yes\n2' > readme.txt

git add .
git commit -m 'ver-yes2'

切换到master分支,再创建分支no:

git checkout master

git checkout -b no

为no分支做两次提交:

# commit ver-no1
echo -e 'no\n1' > readme.txt

git add .
git commit -m 'ver-no1'

# commit ver-no2
echo -e 'no\n2' > readme.txt

git add .
git commit -m 'ver-no2'

再次切换到master分支,这就让HEAD再次指向了master分支

git checkout master

修改一下暂存区的样子:

# stage
echo stage > readme.txt
git add .

最后修改一下工作区的样子:

echo work > readme.txt

搞定。当然,如果你嫌没完没了的敲命令太麻烦,那就搞个sh文件,把这些命令都复制过去。然后执行一次脚本。

Git diff命令的格式

比较工作区

这种最简单,用空参数表示工作区,就是下面的格式:

git diff [] [–] [ …]

例如:比较工作区和暂存区,空参数表示工作区,工作区的上一级就是暂存区,所以也可以为空

$ git diff
diff --git a/readme.txt b/readme.txt
index 0e26ecd..b8f99f5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-stage
+work

这里比较的其实是暂存区的目录树和工作区的对应的目录树。如果只比较少数的文件,可以用-- path的形式。

$ git diff -- readme.txt
diff --git a/readme.txt b/readme.txt
index 0e26ecd..b8f99f5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-stage
+work

例如:比较工作区和commit指向的tree

$ git diff HEAD
diff --git a/readme.txt b/readme.txt
index f2ad6c7..b8f99f5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-c
+work

例如:比较工作区和tag指向的tree

$ git diff a
diff --git a/readme.txt b/readme.txt
index 7898192..b8f99f5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-a
+work

例如:比较工作区和分支指向的tree

$ git diff yes
diff --git a/readme.txt b/readme.txt
index f646a2f..b8f99f5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1 @@
-yes
-2
+work

比较文件

就是不用考虑git中各个对象的因素,直接做文件的比较,就是下面的格式:

git diff [] --no-index [–]

例如:直接比较两个文件

$ echo abc > abc.txt

$ git diff --no-index readme.txt abc.txt
diff --git a/readme.txt b/abc.txt
index b8f99f5..8baef1b 100644
--- a/readme.txt
+++ b/abc.txt
@@ -1 +1 @@
-work
+abc

比较暂存区

暂存区用–staged或–cached,就是下面的格式

git diff [] --cached [] [–] [ …]

例如:比较暂存区和HEAD,因为暂存区的上一级就是提交区,默认就是HEAD:

$ git diff --cached
diff --git a/readme.txt b/readme.txt
index f2ad6c7..0e26ecd 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-c
+stage

例如:比较暂存区和其它commit指向的tree

$ git diff --cached HEAD~1
diff --git a/readme.txt b/readme.txt
index 6178079..0e26ecd 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-b
+stage

例如:比较暂存区和tag指向的tree

$ git diff --cached a
diff --git a/readme.txt b/readme.txt
index 7898192..0e26ecd 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-a
+stage

例如:比较暂存区和分支指向的tree

$ git diff --cached yes
diff --git a/readme.txt b/readme.txt
index f646a2f..0e26ecd 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1 @@
-yes
-2
+stage

比较提交

可以用HEAD标记或tag名称或分支名称指向提交,就是下面的格式:

git diff [] [–] [ …]

git diff [] [–] [ …]

git diff [] … [–] [ …]

这三种格式其实并没有本质的区别。

例如:比较HEAD指向的tree和tag a指向的tree

$ git diff HEAD a
diff --git a/readme.txt b/readme.txt
index f2ad6c7..7898192 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-c
+a

例如:比较HEAD上一个提交指向的tree和分支yes指向的tree

$ git diff HEAD~1 yes
diff --git a/readme.txt b/readme.txt
index 6178079..f646a2f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
-b
+yes
+2

这样的例子有很多,了解规则后完全可以自由发挥。

从公共祖先比较提交

这个格式比较意思,它来源于实际工程需要,并赋予了一种特殊的格式:

git diff [] … [–] [ …]

要演示这个效果,我们需要在当前master分支上再做一次提交:

例如:比较HEAD指向的tree和tag a指向的tree

git add .

git commit -m 'ver-d'

然后我们比较一下yes分支和HEAD:

$ git diff yes HEAD
diff --git a/abc.txt b/abc.txt
new file mode 100644
index 0000000..8baef1b
--- /dev/null
+++ b/abc.txt
@@ -0,0 +1 @@
+abc
diff --git a/readme.txt b/readme.txt
index f646a2f..b8f99f5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1 @@
-yes
-2
+work

这里确实比较出了HEAD和yes分支的所有差异,但是如果我们只想看看yes分支到底做了些什么改变,而不关心master分支在yes分支分叉后做的更多更新,上面的比较结果就显得混乱了。这是一个有实际工程需求的问题,解决起来当然不困难,只需要先找到yes分支开始处的提交,然后让yes分支和这个提交做比较就可以了。但是这样就要做两步才能看到结果。

估计Git是觉得这个需求太常用了,干脆一步到位吧,于是就有了下面的例子:

$ git diff HEAD...yes
diff --git a/readme.txt b/readme.txt
index f2ad6c7..f646a2f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
-c
+yes
+2

这里确实比较出了HEAD和yes分支的所有差异,但是如果我们只想看看yes分支到底做了些什么改变,而不关心master分支在yes分支分叉后做的更多更新,上面的比较结果就显得混乱了。这是一个有实际工程需求的问题,解决起来当然不困难,只需要先找到yes分支开始处的提交,然后让yes分支和这个提交做比较就可以了。但是这样就要做两步才能看到结果。

估计Git是觉得这个需求太常用了,干脆一步到位吧,于是就有了下面的例子:

$ git diff HEAD...yes
diff --git a/readme.txt b/readme.txt
index f2ad6c7..f646a2f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
-c
+yes
+2

可以这样理解…,它是说先别比较HEAD和yes,让我先找找HEAD和yes的公共父节点。好了,找到了,是XXX,然后再比较XXX和yes分支。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值