问题描述
我知道我可以使用git diff
来检查某个文件在两个指定分支之间的差异。
可以在一个命令中为所有分支完成此操作吗?
它还会包括已删除的分支吗?
解决方法
可以在一个命令中为所有分支完成此操作吗?
否。
它还会包括已删除的分支吗?
否。
重要的是要意识到,从某种意义上说,Git确实没有分支。 (尽管如此,它确实有其他含义。)Git的名称是分支名称。尽管它们确实很重要,但它们并不像人们最初想象的那么重要。
Git真正涉及的是提交。它与文件无关,尽管提交包含文件。尽管分支名称标识特定的提交,但与分支名称无关。 Git与 commits 有关。当您运行git diff br1 br2
时,是在告诉Git对两个特定的 commits 进行比较。
每个提交都存储Git知道的(或者更确切地说,在您或其他人进行该提交时)知道的所有文件的完整快照。这是每次提交的主要数据。每个提交还存储一些元数据或有关提交本身的信息,例如谁(姓名和电子邮件地址)进行了提交,何时(日期和时间戳记)以及为什么(它们的日志消息)。提交)。
商品已编号,但数字是外观随机的哈希ID,而不是简单的计数数字。哈希ID实际上完全是 non 随机的,因为它们是提交内数据和元数据的加密校验和。 Git通过其哈希ID查找提交:在存储库中有一个很大的对象数据库,对象由这些哈希ID编号。 (提交是此对象数据库中的四种对象类型之一。)
因为哈希ID 是校验和,所以任何提交的任何部分都无法更改。您通常将 new 提交添加到存储库。 (可以放弃 ,但只能在特定条件下使用。)
每个提交都将其直接前一个提交的哈希ID(有时是哈希ID,复数)存储为元数据的一部分。这样,Git可以从(某个分支的) last 提交开始并向后工作,一次提交一次:
... <-F <-G <-H
这里H
代表某些提交链的 last 提交的哈希ID。在Git可以从对象数据库中读取的提交H
中,有较早提交G
的哈希ID。这样,Git可以在对象数据库中找到G
;在该对象内部,有较早提交F
的哈希ID。这样,Git可以找到具有另一个哈希ID的F
,依此类推。这是Git存储库中的历史记录。
但是这给Git带来了问题。如何快速轻松地找到 last 提交的哈希ID?例如,在上面,Git将在哪里找到哈希ID H
?
分支名称解决了此问题。每个名称都具有一(1)个哈希ID,根据定义,哈希ID是链中的 last 提交。因此,如果master
拥有哈希ID H
,我们将:
...--F--G--H <-- master
如果存在另一个分支名称,则该另一个分支名称将保留某个提交的哈希ID-可能是H
,可能是G
或F
,或者可能是{{1之后的一些提交}}。也许H
拥有某个提交develop
的哈希ID,其提交为I
:
G
现在,名称...--F--G--H <-- master
\
I <-- develop
和名称master
各自选择了一个特定的提交。
您可以运行develop
并为其提供原始哈希ID;或者您可以运行它并为其指定分支名称。当给它命名分支名称时,Git只是查找名称并找到哈希ID,然后对两个哈希ID运行diff。
所以:
有没有一种方法可以比较所有分支上的文件?
是:列举所有有趣的提交,然后以您喜欢的任何方式运行git diff
。例如:
git diff
将以简写形式{git for-each-ref --format='%(refname:short)' refs/heads
,master
等(而不是其全名develop
,{{1 }}等。
要将提交C1中的特定文件的快照与提交C2中的快照进行比较,可以使用:
refs/heads/master
refs/heads/develop
之后的 pathspec 参数将差异限制为仅一个文件。 (git diff C1 C2 -- path/to/file
本身在这里是可选的;出于习惯使用它通常是一个好主意,以避免在更复杂的--
使用中产生歧义。)
如果要比较(例如)名称为--
的提交中的快照与名称为git diff
所标识的提交中的快照:
master
将完成这项工作。因此,如果您想一次将develop
中的提交与每个分支中的提交进行比较:
git diff master develop -- path/to/file
例如,可以解决问题。如上所示,填写master
。
请注意,git for-each-ref ... |
while read branch; do
git diff master $branch -- path/to/file
done
将打印for-each-ref
,因此您将运行一个for-each-ref
,它将从字面上比较master
的小费提交。文件将匹配,这意味着git diff master master -- path/to/file
将不打印任何内容,但这 有点浪费。如果您不喜欢这种浪费,请添加代码以测试master
是否为git diff
,如果是,则跳过$branch
步骤(但请注意,此测试本身还会添加一些计算工作,对于每个 other 名称,这都是很浪费的:TANSTAAFL 1 )。
1 没有免费的午餐