简体   繁体   English

有没有办法比较所有分支的文件?

[英]Is there a way to compare a file over all branches?

I know I can use git diff to check for the difference of a certain file across two specified branches.我知道我可以使用git diff检查两个指定分支中某个文件的差异。
Can it be done for all branches in a single command?可以在一个命令中对所有分支完成吗?
Would it also include the deleted branches?它还会包括已删除的分支吗?

Can it be done for all branches in a single command?可以在一个命令中对所有分支完成吗?

No.不。

Would it also include the deleted branches?它还会包括已删除的分支吗?

No.不。

It's important to realize that in one sense, Git doesn't really have branches .重要的是要认识到,在某种意义上,Git 并没有真正的分支机构 (In several other senses, though, it does.) What Git has are branch names . (不过,在其他几种意义上,它确实如此。)Git 具有的是分支名称 They're not nearly as important as people might think at first, though they are certainly important.它们并不像人们最初想象的那么重要,尽管它们确实很重要。

What Git is really about is commits. Git 的真正含义是提交。 It's not about files , although commits contain files;这与文件无关,尽管提交包含文件; and it's not about branch names , although branch names identify specific commits.这与分支名称无关,尽管分支名称标识了特定的提交。 Git is all about commits . Git 是关于提交的。 When you run git diff br1 br2 , you are telling Git to run a diff on two specific commits .当您运行git diff br1 br2时,您是在告诉 Git 在两个特定的提交上运行 diff。

Every commit stores a full snapshot of all the files that Git knows about—or rather, knew about, at the time you, or whoever, made that commit.每个提交都会存储 Git 知道的所有文件的完整快照——或者更确切地说,在你或任何人进行该提交时知道的所有文件。 That's the main data for each commit.这是每次提交的主要数据。 Each commit also stores some metadata , or information about the commit itself, such as who—name and email address—made the commit, when (date and time stamp), and why (their log message for the commit).每个提交还存储一些元数据,或有关提交本身的信息,例如提交人(姓名和 email 地址)、提交时间(日期和时间戳)以及原因(他们的提交日志消息)。

Commits are numbered, but the numbers are random-looking hash IDs, rather than simple counting numbers.提交已编号,但数字是随机的 hash ID,而不是简单的计数数字。 The hash IDs are actually entirely non -random, as they are cryptographic checksums of the data-and-metadata inside the commit. hash ID 实际上完全是非随机的,因为它们是提交中数据和元数据的加密校验和。 Git finds the commits by their hash IDs: there is a big object database inside the repository, with objects being numbered by these hash IDs. Git 通过其 hash ID 找到提交:存储库中有一个大的object 数据库,对象由这些 hash ID 编号。 (Commits are one of four object types within this object database.) (提交是此 object 数据库中的四种 object 类型之一。)

Because the hash IDs are checksums, no part of any commit can ever be changed.因为 hash ID校验和,所以任何提交的任何部分都不能更改。 You mostly add new commits to a repository.您主要将提交添加到存储库。 (Commits can be forgotten, but only under particular conditions.) (提交可以被遗忘,但只有在特定条件下。)

Each commit stores, as part of its metadata, the hash ID—or sometimes hash IDs, plural—of its immediate predecessor commits.作为其元数据的一部分,每个提交都会存储其直接前任提交的 hash ID(有时是复数形式的 hash ID)。 In this way, Git can start with the last commit (of some branch) and work backwards, one commit at a time:这样,Git 可以从(某个分支的)最后一次提交开始并向后工作,一次一个提交:

... <-F <-G <-H

Here H stands in for the hash ID of the last commit of some chain of commits.这里H代表一些提交链的最后一次提交的 ID hash。 Inside commit H , which Git can read out of the object database, there is the hash ID of earlier commit G .在提交H中,Git 可以从 object 数据库中读出,其中有早期提交G的 ID hash。 That lets Git find G in the object database;这让 Git 在 object 数据库中找到G inside that object there is the hash ID of earlier commit F .在 object 里面有早期提交F的 hash ID。 That lets Git find F , which has another hash ID, and so on.这让 Git 找到F ,它有另一个 hash ID,等等。 This is the history, in the Git repository.历史,在 Git 存储库中。

But this leaves Git with a problem.但这给 Git 留下了一个问题。 How will it quickly and easily find the hash ID of the last commit?它如何快速轻松地找到最后一次提交的 hash ID? For instance, in the above, where will Git find hash ID H ?例如,在上面,Git 会在哪里找到 ID H hash?

A branch name solves this problem.分支名称解决了这个问题。 Each name holds one (1) hash ID, which is, by definition, the last commit in the chain.每个名称都包含一 (1) 个 hash ID,根据定义,这是链中的最后一次提交。 So if master holds hash ID H , we have:所以如果master拥有 hash ID H ,我们有:

...--F--G--H   <-- master

If there is another branch name, that other branch name holds the hash ID of some commit—maybe H , maybe G or F , or maybe some commit after H .如果有另一个分支名称,则该其他分支名称包含某个提交的 hash ID——可能是H ,可能是GF ,或者可能是H之后的某个提交。 Perhaps develop holds the hash ID of some commit I , whose parent is G :也许develop持有某个提交I的 hash ID,其父项是G

...--F--G--H   <-- master
         \
          I   <-- develop

So now the name master and the name develop each pick out one specific commit.所以现在名称master和名称develop各自挑选出一个特定的提交。

You can run git diff and give it raw hash IDs;您可以运行git diff并为其提供原始 hash ID; or you can run it and give it branch names.或者你可以运行它并给它分支名称。 When you give it branch names, Git just looks up the names and finds the hash IDs, then runs the diff on the two hash IDs.当你给它分支名称时,Git 只是查找名称并找到 hash ID,然后在两个 hash ID 上运行 diff。

So:所以:

Is there a way to compare a file over all branches?有没有办法比较所有分支的文件?

Yes: enumerate all the interesting commits, and then run git diff in whatever way you like.是的:枚举所有有趣的提交,然后以您喜欢的任何方式运行git diff For instance:例如:

git for-each-ref --format='%(refname:short)' refs/heads

will print (to standard output) each branch name, in the short form ( master , develop , etc., rather than as their full names, refs/heads/master , refs/heads/develop , etc.).将打印(到标准输出)每个分支名称,以缩写形式( masterdevelop等,而不是它们的全名, refs/heads/masterrefs/heads/develop等)。

To compare the snapshot of a particular file in commit C1 to that in some commit C2, you would use:要将提交 C1 中特定文件的快照与某个提交 C2 中的快照进行比较,您可以使用:

git diff C1 C2 -- path/to/file

The pathspec argument after the -- limits the diff to just that one file. --之后的pathspec参数将差异限制为仅那个文件。 (The -- itself is optional here; it's generally a good idea to use it out of habit, to avoid ambiguity when you get into more complicated git diff usage.) (这里--本身是可选的;出于习惯使用它通常是个好主意,以避免在使用更复杂git diff时出现歧义。)

If you want to compare the snapshot in (say) the commit identified by the name master to the snapshot in the commit identified by the name develop :如果您想将(比如说)由名称master标识的提交中的快照与由名称develop标识的提交中的快照进行比较:

git diff master develop -- path/to/file

will do the job.会做的工作。 So if you want to compare, one at a time, the commit in master to the commit in each branch:因此,如果您想一次比较master中的提交与每个分支中的提交:

git for-each-ref ... |
    while read branch; do
        git diff master $branch -- path/to/file
    done

would do the trick, for instance.例如,可以解决问题。 Fill in the for-each-ref as seen above.如上所示填写for-each-ref

Note that for-each-ref will print master , so you'll be running one git diff master master -- path/to/file , which will literally compare the tip commit of master to itself.请注意, for-each-ref将打印master ,因此您将运行一个git diff master master -- path/to/file ,它会将master的 tip 提交与其自身进行字面上的比较。 The file will match, which means git diff will print nothing, but this is slightly wasteful.该文件将匹配,这意味着git diff将不打印任何内容,但这有点浪费。 If you don't like the wastefulness, add code to test whether $branch is master and if so, to skip the git diff step (but note that this test itself also adds a bit of compute work, which for every other name, is slightly wasteful: TANSTAAFL 1 ).如果您不喜欢这种浪费,请添加代码来测试$branch是否为master ,如果是,则跳过git diff步骤(但请注意,此测试本身也增加了一些计算工作,对于其他每个名称,是有点浪费:TANSTAAFL 1 )。


1 There Ain't No Such Thing As A Free Lunch 1天下没有免费的午餐

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM