在hg或git中比较两个完整目录/项目的不同?

87

我继承了一个最初存储在CVS中的项目,包括所有修订。我进行了相当多的编辑,并尝试比较原始目录中我所做的所有更改,就新增文件与旧文件而言。

是否有一种hg/git实用程序,可以进行树差异或类似的操作?例如,标记新添加的文件、删除的文件之间的区别,我是不是要求太多了?


git diff master..yourbranch path/to/folder 是一个 Git 命令,用于比较 master 分支和当前分支(yourbranch)中指定文件夹的差异。 - CrandellWS
8个回答

142

要从两个任意文件或目录中,不需要使用任何复杂的存储库工具或版本控制简单地创建Git差异补丁,请执行以下操作:

注:原文中已经使用了“简单地”等表达方式,为了使翻译更加通俗易懂,我在翻译时加粗了一些关键词。保留了HTML标记,没有添加解释。

git diff --no-index some/path other/path > some_filename

Jakub Narębski的评论暗示了knittl答案的答案...为简单起见,这就是完整的命令。

>部分创建文件并将输出重定向到该文件。如果您不想要文件,只想在控制台中打印输出以便您可以复制它,请删除> some_filename 部分。


为方便复制和粘贴,如果您已经使用cd命令进入包含原始目录/文件a和修改后目录b的目录,则命令如下:

git diff --no-index a b > patch

要使用 git diff 选项,请在路径之前添加选项。例如,git diff --name-status --no-index some/path other/path--name-status 选项一起使用。 - Shaun Luttin
1
使用 --binary 用于二进制文件,否则补丁将只显示 "二进制文件不同"。 - qwr
从git-diff手册中:“当在Git控制的工作树中运行命令并且至少有一个路径指向工作树之外时,或者在Git控制之外的工作树中运行命令时,可以省略--no-index选项。” - qwr

25

git diff手册

git diff [--option] [--] [<path>...]

[...]
如果给定了恰好两个路径,且至少有一个未被跟踪,则比较这两个文件/目录。可以通过--no-index强制此行为。


如果要比较两个版本(例如两个标记的发布版或两个分支)在两个不同的存储库中,您可以使用GitWiki页面上描述的技巧,在“如何比较两个本地存储库”下找到。假设您在一个存储库内部,第二个存储库位于/path/to/repo,因此如果它是非裸存储库,则其GIT_DIR为/path/to/repo/.git,可以按照以下方式进行操作:

$ GIT_ALTERNATE_OBJECT_DIRECTORIES=/path/to/repo/.git/objects \
   git diff $(git --git-dir=/path/to/repo/.git rev-parse --verify A) B

其中A和B是您要比较的修订版本。当然,您还可以在上述表达式中指定路径限制器。

解释: GIT_ALTERNATE_OBJECT_REPOSITORIES 变量可用于使 git 命令串联两个存储库的对象数据库。git --git-dir=... rev-parse ... 用于将作为参数给定的存储库中的名称(扩展SHA-1表达式)转换为唯一的SHA-1标识符。$( ... ) 结构将调用给定命令的结果放入命令行中。git diff 用于比较两个修订版本(其中一个来自另一个对象库)。

另一种解决方案是简单地将其他存储库“导入”到给定存储库中,使用git remote add(和git fetch)。 然后,您就可以在单个存储库内比较所有内容了。


17

是否有针对hg/git的实用程序可以进行树形差异比较...以便在新添加的文件、删除的文件之间放置标记...[强调部分已添加]

是的。我们可以使用git diff将当前目录与另一个目录进行比较,并且...

...标记添加、删除和修改的文件:

git diff --name-status --no-index ./ path/to/other/dir

...仅显示添加的文件:

git diff --diff-filter=A --name-status --no-index ./ path/to/other/dir

... 仅显示已删除的文件:

git diff --diff-filter=D --name-status --no-index ./ path/to/other/dir

...仅显示修改过的文件:

git diff --diff-filter=M --name-status --no-index ./ path/to/other/dir

参见:https://git-scm.com/docs/git-diff


11

虽然它并不是只适用于git,但作为一个通用的Windows差异性工具,我非常喜欢 WinMerge


8

我不太明白你想要什么,但是 diff -ur 对你来说不够吗?它甚至可以在没有任何版本控制的目录上工作。


不确定为什么“-u”是这个答案的一部分。“-r”递归地遍历目录。“-q”非常有用,如果你不想看到所有的差异,而只是想知道哪些文件发生了变化。 - paleonix
是的,-u 是用于生成统一格式的差异文件。与递归本身无关。 - Thiago Arrais

5

git diff 的作用就是对比文件差异。但它只适用于 Git 项目。

hg diffsvn diff 等几乎所有版本控制系统都可以对比目录树的差异。


3
当您使用"git diff"命令时,会比较两个不同的Git项目之间的差异。对于您创建的两个不同的Git项目,您可以通过在终端中输入"git diff <path to project 1> <path to project 2>"来比较它们之间的差异。请注意,此命令将显示两个项目之间的所有更改,包括添加、删除和修改的文件和代码行。作为VCS新手,可能需要花些时间来理解和解释diff输出结果。 - meder omuraliev
1
你只需要一个项目。提交所有文件,进行更改后再次提交。然后你可以执行 git diff HEAD^..HEAD 命令,该命令会将你最新版本与之前的版本进行比较。 - knittl
好的 - 我想我得到了我想要的,因为我看到了大量的结果,你能推荐一个不错的 GUI 吗? - meder omuraliev
尝试使用 gitkgit guigitk 可视化项目历史,git gui 允许您准备提交和其他操作。 - knittl
34
实际上,git diff可以比较任意的文件/目录;你可能需要使用它的--no-index选项。 - Jakub Narębski

1
以下是比较两个完整目录/项目的其他方法:
1. Git中有语法: 语法:git-diff [] [--] […​] 这种形式用于查看相对于索引(下一个提交的暂存区)所做的更改。换句话说,差异是您可以告诉Git进一步添加到索引但尚未添加的内容。
这里是URL: https://git-scm.com/docs/git-diff git diff --no-index directory 1 project /path directory 2 project/path >> 文件名
2. 使用Linux命令diff --brief --recursive dir1path/ dir2Path/ 3. 如果您使用Windows,则有一个名为WinMerge的应用程序。

0

从dir1到dir2创建补丁(仅对二进制文件需要--binary):

git diff --no-prefix --no-index --binary dir1 dir2 > dir.diff

将补丁应用于工作目录的内容,该目录与dir1具有相同的内容:

cd dir1_copy
git apply ../dir.diff

git apply 默认使用 -p1,该选项会在 diff 命令中去除前导目录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接