在同一分支上比较两个不同提交中同一文件的差异

在同一分支上比较两个不同提交中同一文件的差异

技术背景

在软件开发过程中,我们经常需要比较同一文件在不同提交之间的差异,以便了解代码的变更历史、进行代码审查等。Git 作为一款强大的版本控制系统,提供了多种方法来实现这一需求。

实现步骤

1. 使用 git diff 命令比较同一文件在不同提交间的差异

git diff 命令的基本语法为:git diff [--options] <commit> <commit> [--] [<path>...]

例如,要查看文件 "main.c" 在当前提交和两个提交之前的差异,可以使用以下三种等效命令:

1
2
3
$ git diff HEAD^^ HEAD main.c
$ git diff HEAD^^..HEAD -- main.c
$ git diff HEAD~2 HEAD -- main.c

2. 比较两个不同版本中的不同文件

可以使用以下语法比较两个不同版本中的不同文件:

1
git diff <revision_1>:<file_1> <revision_2>:<file_2>

3. 使用 git difftool 进行可视化比较

如果配置了 difftool,可以使用以下命令进行可视化比较:

1
git difftool revision_1:file_1 revision_2:file_2

示例:比较同一分支上一个文件的最后一次提交和上一次提交的差异:

1
$ git difftool HEAD:src/main/java/com.xyz.test/MyApp.java HEAD^:src/main/java/com.xyz.test/MyApp.java

需要在 ~/.gitconfigproject/.git/config 文件中添加以下配置,并安装 p4merge

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[merge]
tool = p4merge
keepBackup = false
[diff]
tool = p4merge
keepBackup = false
[difftool "p4merge"]
path = C:/Program Files (x86)/Perforce/p4merge.exe
[mergetool]
keepBackup = false
[difftool]
keepBackup = false
[mergetool "p4merge"]
path = C:/Program Files (x86)/Perforce/p4merge.exe
cmd = p4merge.exe "$BASE" "$LOCAL" "$REMOTE" "$MERGED"

4. 在 IntelliJ 中进行差异比较

在 IntelliJ 中,可以通过右键点击 -> Git -> Compare with revision 来选择要比较的版本,IntelliJ 会显示差异。

5. 根据 git log 结果生成 git diff 命令

可以使用 Perl 脚本根据 git log 的结果生成 git diff 命令,示例脚本 gldiff.pl 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# gldiff.pl
use strict;

my $max = shift;
my $file = shift;

die "not a number" unless $max =~ m/\d+/;
die "not a file" unless -f $file;

my $count;
my @lines;

while (<>) {
chomp;
next unless s/^commit\s+(.*)//;
my $commit = $1;
push @lines, sprintf "%s:%s", substr($commit,0,6),$file;
if (@lines == 2) {
printf "git diff %s %s\n", @lines;
@lines = ();
}
last if ++$count >= $max *2;
}

使用方法:

1
git log pom.xml | perl gldiff.pl 3 pom.xml

6. 比较多个文件或非连续提交

可以通过创建临时分支来比较多个文件或非连续提交:

1
2
3
4
5
6
7
8
9
10
# 创建临时分支
git checkout -b revision
# 回退到第一个提交目标
git reset --hard <commit_target>
# 挑选感兴趣的提交
git cherry-pick <commit_interested> ...
# 应用差异
git diff <commit-target>^
# 完成后删除临时分支
git branch -D revision

7. 比较多个文件

可以使用以下命令比较多个文件:

1
git diff master..HEAD -- `find your_search_folder/ -name '*.coffee'`

8. 避免知道最近提交的 ID

可以使用以下命令:

1
git difftool HEAD HEAD@{N} /PATH/FILE.ext

核心代码

以下是前面提到的 Perl 脚本 gldiff.pl 的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# gldiff.pl
use strict;

my $max = shift;
my $file = shift;

die "not a number" unless $max =~ m/\d+/;
die "not a file" unless -f $file;

my $count;
my @lines;

while (<>) {
chomp;
next unless s/^commit\s+(.*)//;
my $commit = $1;
push @lines, sprintf "%s:%s", substr($commit,0,6),$file;
if (@lines == 2) {
printf "git diff %s %s\n", @lines;
@lines = ();
}
last if ++$count >= $max *2;
}

最佳实践

  • 选择合适的工具:根据具体需求选择合适的比较工具,如简单的文本差异可以使用 git diff,需要可视化比较可以使用 git difftool 或 IDE 提供的比较功能。
  • 使用临时分支:在比较多个文件或非连续提交时,使用临时分支可以避免对当前工作分支造成影响。
  • 脚本自动化:对于重复性的比较任务,可以编写脚本进行自动化处理,如上述的 Perl 脚本。

常见问题

  • difftool 配置问题:如果 difftool 无法正常工作,可能是配置文件中的路径或工具名称有误,需要检查 ~/.gitconfigproject/.git/config 文件中的配置。
  • 脚本运行问题:如果 Perl 脚本运行出错,可能是输入参数不符合要求,需要确保输入的参数是有效的数字和文件。

在同一分支上比较两个不同提交中同一文件的差异
https://119291.xyz/posts/compare-file-differences-between-two-commits/
作者
ww
发布于
2025年6月19日
许可协议