Git 使用--允许不相关的历史记录来维护历史记录?

Git 使用--允许不相关的历史记录来维护历史记录?,git,rebase,Git,Rebase,我有两个回购协议foo和bar,它们没有共同的根我想合并这两个回购协议,保留它们的历史记录 我需要维护foo的提交历史记录。。我希望将bar的历史作为一个离散补丁重新建立在foo之上 比如说, repofoo有文件/baz,提交A,B,C repobar具有文件/baz和提交、D、E 我希望生成的repofoo将/baz的提交按如下顺序排序:A,B,C,D,E 当D着陆时,应始终将其视为正确和完整 连接两个回购的首选方法似乎是——允许不相关的历史记录和合并,但我需要知道如何在合并后维护历史记

我有两个回购协议
foo
bar
它们没有共同的根我想合并这两个回购协议,保留它们的历史记录

我需要维护
foo
的提交历史记录。。我希望将
bar
的历史作为一个离散补丁重新建立在
foo
之上

比如说,

  • repo
    foo
    有文件
    /baz
    ,提交
    A
    B
    C
  • repo
    bar
    具有文件
    /baz
    和提交、
    D
    E
我希望生成的repo
foo
/baz
的提交按如下顺序排序:
A
B
C
D
E

D
着陆时,应始终将其视为正确和完整


连接两个回购的首选方法似乎是
——允许不相关的历史记录和合并,但我需要知道如何在合并后维护历史记录。

好消息是,您可以得到您想要的:在Git存储库中,历史记录只是提交

提交已编号。这些数字是散列ID,它们对于每个提交的内容都是唯一的。如果两个不同Git存储库中的两个提交的内容完全匹配,那么它们的哈希ID也完全匹配。如果内容不同,则它们的哈希ID也不同

Git存储库的历史记录是其存储库中的一组提交。要保留您称为“foo的提交历史记录”的历史记录,您需要保留这些确切的提交及其确切的内容。幸运的是,这也是你在这里想要做的:

我想把
bar
的历史作为一个独立的补丁重新建立在foo之上

并没有提交是一个“离散补丁”,所以你们的意思必须是你们想从bar复制提交的部分或全部内容

也就是说,我们将从提交存储库
foo
开始。我们将按原样将它们复制到新的组合存储库中,以便它们是相同的提交,具有相同的哈希ID。然后,我们将从存储库
中取出每个提交,在它不在Git中时作为提交对其进行更改,并将结果作为新提交放回组合存储库中

新提交不同于以前的任何提交,它将有自己的新的和唯一的哈希ID。因此,只保留存储库
foo
的历史记录

当[repo
bar
]的第一次提交到达时,应始终将其视为正确且完整

现在我们开始讨论每个提交的内容,现在我们来看看提交的机制

正常过程 通常,当我们进行新的提交时,我们通过以下方式进行:

  • 从某个现有存储库的克隆开始,或从某个现有存储库开始。两者都可以,因为提交是通过克隆复制的,因此克隆具有相同的哈希ID。(不会复制分支名称克隆会获得自己的分支名称,但Git中的分支名称并不重要,除了查找提交哈希ID之外。)

  • 正在提取其中一个提交:
    git签出名称
    或(git 2.23或更高版本)
    git开关名称
    。这将使用名称查找提交的哈希ID。Git然后将提交的快照部分复制到两个位置:

    • 一个副本进入Git的索引。这就是Git将用来创建下一个提交快照的内容

    • 另一个副本进入您的工作树。提交中的文件除了作为存档快照之外,对任何东西都没有用处:它们是压缩的、重复数据消除的,通常只能由Git本身读取。因此,它们必须被取消归档并扩展成有用的形式。Git不需要这些文件:每个文件的工作树副本都是为您准备的,因为您需要这种形式的文件

  • 现在我们处理这些文件,也许会更改其中的一些。如果我们确实更改了其中一些,并且想要创建一个新的快照,我们必须使用
    git add
    将更新的文件复制回git的索引中,启动旧的副本并用更新的文件替换它。(或者,如果文件是全新的,我们不启动任何东西,只添加一个新文件。)

  • 然后我们运行
    git commit
    :git使用git从您的
    user.name
    user.email
    设置和其他信息构造的全新元数据进行新的提交。新提交的快照来自Git的索引。提交的总体内容是快照和元数据

在将新提交写入all commits和其他Git对象数据库之后,Git会将新提交的新的唯一哈希ID隐藏到当前分支名称中,以便Git可以使用当前分支名称找到新提交。新的提交现在一直处于冻结状态:此哈希ID现在已用完,表示此提交

你想要什么 首先,将
foo
存储库作为一个整体进行克隆,以便获得其所有三个提交,
a-B-C
。这三次提交中的每一次都有每个文件的完整快照。这是一个正常的日常克隆操作,工作方式通常是:复制所有提交,不复制任何分支,然后创建一个与源存储库的分支名称匹配的新分支名称,并保留相同的提交哈希ID

接下来,您可能需要
git-remote添加
bar
存储库,这样您就可以
git-fetch
所有提交:在本例中,
D
E
。这些也是每个文件的完整快照

现在由您决定如何从组合存储库中获取快照和元数据
D
,并创建一个新的、不同的提交
D'
,其中包含快照和
A--B--C   <-- foo/main
       \
        D'-E'   <-- main (HEAD)

D--E   <-- bar/main
A--B--C   <-- main (HEAD), foo/main

D--E   <-- bar/main
git replace --graft bar/main~1 main
A--B--C   <-- main (HEAD), foo/main
       \
        D'  <-- refs/replace/<hash>

D--E   <-- bar/main
git reset --hard bar/main
git merge --ff-only bar/main
A--B--C   <-- foo/main
       \
        D'  <-- refs/replace/<hash>

D--E   <-- main (HEAD), bar/main
A--B--C   <-- foo/main
       \
        D'  <-- refs/replace/<hash>
         \
          E'

D--E   <-- bar/main, main (HEAD)
A--B--C   <-- foo/main
       \
        D'  <-- refs/replace/<hash>
         \
          E'  <-- main (HEAD)

D--E   <-- bar/main
A--B--C   <-- foo/main
       \
        D'-E'  <-- main (HEAD)
A--B--C   <-- foo/main

D--E   <-- main (HEAD), bar/main
D-----E   <-- bar/main
       \
        M   <-- main (HEAD)
       /
A--B--C   <-- foo/main
--follow
  Continue listing the history of a file beyond renames (works only for a single file)