3

我有一种情况,我有两个已被复制和损坏的存储库历史记录(通过围绕 SVN 的交互和迁移——不是我的选择)。我在同一个临时维护存储库中将两个存储库作为远程存储库。他们共享数百个历史提交,然后“旧”提交在几个分支上继续进行几十个。我需要将“新”树快进到旧树的状态。然而,由于重整,尽管它们具有相同的内容,但它们不会被识别为同一棵树。

我想告诉 git “这两个提交是相同的,尽管作者不同”(作者 ID 在翻译中被混淆了)。如果可能的话,我真的很喜欢它是否可以遍历两个远程树并为每个具有相同内容的节点建立关联。这意味着我可以在两者上手动标记“commit 1”,然后让它完成剩下的工作。否则我需要手动标记每个分歧的根源(不会太糟糕,但不希望这样做)。

我尝试使用移植点,这几乎是我想要的——gitk 显示了我想要的,但是当我将它推回主(新)存储库时,它拖着数百个重复提交。这样做也有点烦人,因为我必须为尚未合并的子节点这样做。

我找到了https://stackoverflow.com/a/973403/372757,并认为它会起作用:我只需要将旧提交重新定位到新存储库,每个分支一次。

尽管如此,我仍然想知道我最初的请求是否可行。

4

2 回答 2

4

git对什么是“相同的提交”有一个非常严格的定义,这可能与您的想法不符。为了成为相同的提交,以下所有条件都必须为真:

  1. 树中要提交的每个文件都必须与提交中将成为新提交的父文件(即当前 HEAD)的同一文件逐字节相同
  2. 没有新文件,没有删除文件,没有重组 - 树必须完全匹配,因为树的 SHA1 取决于它包含的文件和子树;如果树上的任何叶子不同,则顶层树的 SHA1 将不同
  3. 完全相同的作者和提交者姓名和电子邮件值
  4. 完全相同的作者和提交日期
  5. HEAD 的当前值完全相同,它成为新提交的父级
  6. 完全相同的提交信息
  7. 可能还有我遗漏的其他一些细节

所有这些东西都直接或间接用于为新提交生成 SHA1 哈希,因此除非真正相同,否则提交不会相同。

也就是说,我认为可能更符合您的问题,在生成新提交时,如果特定文件或树与数据库中已经存在的对象逐字节相同,因为另一个提交具有那些处于完全相同状态的事物,那么新的提交将指向那些已经存在的对象——它们不会被再次存储。

如果只有两个分支中不同的作者信息(这将是不同的提交序列,即使文件内容与另一个分支完全匹配),您可以使用git filter-branchgit rebase重写一个分支,随时修复信息,但是将导致一组全新的提交(但所有树和文件对象都可能保持不变,假设您除了提交消息、时间或作者/提交者名称之外没有更改任何内容)。但是请注意,如果其他工作(您自己或其他人)已经基于现有分支,则进行此类更改可能会涉及大量清理工作。

于 2012-11-02T20:31:55.937 回答
1

您的问题是重新定义提交平等。我认为您应该使用git cat-filegrep过滤提交的相关信息。也许树线对你来说已经足够了(比如,git cat-file commit <COMMIT_ID> | grep "tree"),但我认为包含父树也很好(不仅仅是提交的 ID,因为它们会有所不同)。

git rev-list一旦你有了这个相等功能,我认为你的 repo 和对它们进行一些重复搜索就很重要了。

于 2012-11-02T22:45:14.147 回答