Git比较提交的标准,为什么包括提交者?

MP0*_*MP0 5 git commit github

Git使用SHA1哈希来标识提交对象,根据Git Book,提交对象包含:

  • 一颗树
  • 指向旧提交(父)的指针
  • 时间戳
  • 作者的名字
  • 提交者名称
  • ...

令我惊讶的是既需要作者commiter在提交对象,的确是一个迅速合并问题提交到另一个相同的存储库时,由于提交哈希会改变!

我的观点由GitHub说明,在您的Fork Queue中,一旦您的更改与原始项目合并,您甚至可以找到自己的提交!它通常是一个"metaconflict",因为发起变更的人是相同的,谁提交不应该改变提交的性质 ......

那么,为什么需要呢?是滥用作者和提交者吗?我理解两者的需要,我不明白为什么两者都应该包含在提交哈希中,为什么不在其他地方呢?

可以不同意在不同的repos中提交的相同更改应该被标识为相同,因此从哈希中排除提交者的名称吗?

djs*_*djs 6

即使作者以外的其他人提交到树,commiter字段也允许您保留作者身份.这在"拉"开发模型中至关重要,在这种模型中,维护人员可能会从可能不允许直接推送到存储库的各个开发人员那里获取更改.在没有这些字段的版本控制系统中,作者似乎是有权推动更改的任何人.

由于作者可能已经在一个分支中进行了更改,但两者都有助于识别实际上对特定分支进行了更改的人员,但之后它被挑选到了另一个分支.


seh*_*ehe 3

上述识别是关键。

当您意识到 Git 能够对提交进行强签名时,这一切就会变得更有意义;这样就没有人可以伪造历史,甚至连责任人的名字也不能伪造:)


评论:Git 还关乎来源的信任和可验证性。简而言之:提交者负责提交并对其进行签名(字面意思);作者是第一个提交补丁的人 - 这可能是“外部”的人,“不受信任”的人。(_如果您对此难以理解,请考虑 Linux 内核项目、安全漏洞或后门:Linux 用户确实需要验证他们使用的内核是否已由受信任的社区成员审核!


附加信息:“真正的”问题

以我为例,我是一个提交的作者,它是由主项目的所有者提交的,当我查看我的分叉队列时,我看到我自己的提交(同一作者)被要求提交(再次)到我的叉子?没有办法说这是同一个东西!

啊,这是真正的问题!因此,您不必担心为什么要对提交进行校验和(包括注释和其他元数据)。你也不用担心为什么会有committerauthor字段[1]

您对合并提交具有不同提交 ID 的事实感到恼火,除非它是 ff(快进)合并。现在有一个好问题!答案如下

提交 ID 也取决于父提交,因此提交 ID 只能在以下情况下相同:

  1. 父 ID 相同
  2. 提交的树“快照”是相同的

发生这种情况的唯一情况是分叉(引用相同的提交)和快进合并(导致...相同的引用)[2]。

因此,一旦您合并、cherry-pick 或 rebase(在这种情况下是三个类似的操作),即使是单个提交到不同的分支(在不同的父提交下读取),根据定义,它也将具有不同的提交 ID,无论对哪些元数据进行校验和。这是因为树历史不同,这是此时唯一相关的元数据。

真正的问题是:如何避免看到重复提交?

  • 更喜欢合并而不是cherry-pick/rebase

    • 合并时,生成的提交将有两个父提交;这使得 git 能够进行合并跟踪并自动消除重叠提交(即已经合并的提交)。git diffgit merge-basegit log rev1 ^rev2、 git show-branch 都遵循这个逻辑)。这就是为什么重复合并(十字形、燕尾形等)在 git 上能够“神奇地”工作。[3]

      • 怀疑:如果您向上游发送拉取请求,他们可能不会合并您的分支,从而使此建议“难以”实现。然而,没有什么能阻止你

        • 在他们接受你的工作后合并他们的分支(相同的最终结果,更多的工作)
        • 在他们接受你的工作后,将你自己的分支重新定位到他们的分支(相同的最终结果)

  • 使用例如检查发生了cherry-picks或rebase的分支之间的差异。从联机帮助页来看,这正是您想要的:git log --left-right --graph --oneline --cherry-pick BRANCH1...BRANCH2
  --cherry-pick
       Omit any commit that introduces the same change as another commit on the "other side" when the set of commits are limited with symmetric
       difference.

       For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right, like the example
       above in the description of that option. It however shows the commits that were cherry-picked from the other branch (for example, "3rd on b" may
       be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.
Run Code Online (Sandbox Code Playgroud)
  • 最后,如果您的情况是经常发生冲突的合并情况之一(例如在使用非中心主题分支时),请参阅` git rerere --help,这超出了我的答案的范围。

[1] 你甚至不用担心提交注释,它们是带外的,没有修订也没有校验和......原文如此

[2] 在技术方面的胡言乱语:提交历史形成了密码学上强大的默克尔树。当提示提交 (HEAD) 的 sha1 总和匹配时,从数学角度来看,(a) 树内容 (b) 分支历史记录(包括所有签核和提交者/作者凭证)是相同的。这是 git 和其他具有此功能的 SCM 的一个巨大的安全功能。

[3] 另请参阅git log --merges --boundaries --decorate修订版规格,例如 rev1...rev2(注意三个点;请参阅man git-rev-parse