【问题标题】:Merge two Git repos and keep the history合并两个 Git 存储库并保留历史记录
【发布时间】:2017-02-17 07:45:38
【问题描述】:

我想补充我的另一个问题:Merge two Git repositories and keep the master history

我已经成功地将 2 个不同的 repo 合并到一个 repo 中。我需要一个变基才能成功地做到这一点。大师是正确的,但我也想保留合并历史。这可能吗?

我有 2 个存储库:

这是变基后的结果。 top repo 的时间是rebase-time。原始日期已丢失!

我就是这样做的:

# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init

# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
dir > Read.md
git add .
git commit -m "initial commit"

# Add a remote for and fetch the old RepoA
git remote add -f RepoA https://github.com/DimitriDewaele/RepoA

# Do the same thing for RepoB
git remote add -f RepoB https://github.com/DimitriDewaele/RepoB

# Rebase the working branch (master) on top of repoB
git rebase RepoB/master

# Rebase the working branch (master with RepoB) on top op repoA
git rebase RepoA/master

有可能有这样的东西吗?涂漆解决方案!!!

我想保留原始时间+合并历史。

更新 - 答案

最适合我的答案是使用嫁接点。但其他答案在其他用例中也非常有用。我已经把我的结果加到了github上,大家可以评价一下。

答案 1:最适合我的情况“移植”确实为我揭示了正确的工作答案。

GitHub: RepoGraft

答案 2“LeGEC”中的“替换”选项对于某些用例也有很好的效果。一个异常留给我:

GitHub: RepoHistory

答案 3:值得补充 来自“VonC”的答案。在我的情况下,我无法获得“--preserve-merges working”选项。这可能适用于其他场景,但我没有测试这个furtner。

【问题讨论】:

  • 你想保留 repoA 只是为了能够检查它的历史吗?还是 repoA 是一个实时存储库,有新的提交、拉取请求等?
  • @LeGEC 我只想用分支历史来检查历史。新的工作将在生成的 repo 之上发生。

标签: git merge repository rebase


【解决方案1】:

正如您所发现的,rebase 不是您想要用来将历史拼接在一起的命令(因为它实际上会重写历史)。早期的 Git 有一个专门为你想要做的事情设计的功能(hack):graft points。更好的是,从 1.6.5 开始,您可以改用 git replace --graft

git checkout master
git replace --graft $(git log RepoB/master --format=%H | tail -1) HEAD
git replace --graft $(git log RepoA/master --format=%H | tail -1) RepoB/master
git reset --hard RepoA/master

git log RepoA/master --format=%H | tail -1 返回来自RepoA 的初始提交)

从技术上讲,如果您在 master 中实际上还没有任何有价值的东西,您可以跳过第一个 replace,只产生 RepoB + RepoA 的历史记录。

这些命令在refs/replace/* 中创建条目,可以推送和拉取这些条目以与他人分享您修改过的历史记录。或者,如果您不关心保留 RepoA/RepoB 的 SHA,则可以通过运行 git filter-branch --all 来生成替换永久,以生成所需谱系的“真实”提交集。

【讨论】:

    【解决方案2】:

    git rebase 中有两个选项应该对您的情况感兴趣:

    p
    --preserve-merges
    

    重新创建合并提交,而不是通过重放合并提交引入的提交来展平历史。

    --committer-date-is-author-date 
    

    (来自git am

    默认情况下,该命令将电子邮件消息中的日期记录为提交作者日期,并使用提交创建时间作为提交者日期。这允许用户通过使用与作者日期相同的值来谎报提交者日期。

    测试第二个 rebase 是否没有产生更好的结果:

    git rebase -p --committer-date-is-author-date RepoA/master
    

    【讨论】:

    • 请注意,--committer-date-is-author-date 仍然将提交者更改为 rebaser,这可能是也可能不是问题。您真的只是不想为此使用rebase
    • @dahlbyk 我知道。我建议将其作为快速修复,但旧的嫁接点也可以完成这项工作。 +1
    • 确实,值得了解的好选择。只是不适用于这个特殊问题。 :)
    【解决方案3】:

    这个答案提出了一种使用 RepoB 作为活动仓库的不同方式,并且仍然可以访问 RepoA 历史记录:

    使用git replace

    # start with a regular clone of the active repo :
    $ git clone RepoB
    
    # add repoA as a remote :
    $ git remote add -f history https://github.com/DimitriDewaele/RepoA
    
    # get hash of *initial* commit on repoB :
    $ git log --oneline origin/master | tail -1
    abcdef Initial commit
    
    # get hash of last commit on repoA :
    $ git log --oneline history/master | head -1
    12345 Merge branch 'develop'
    
    # use 'git replace' to tell git to stitch histories in the log :
    $ git replace abcdef 12345
    

    注意:此操作是在您的机器上完成的,而不是在远程存储库上,因此应在所有新克隆上重复。

    变体

    您可以以新名称(例如:RepoB:history/master)将RepoA:master 推送到RepoB,然后您可以在所有存储在RepoB 中的提交上使用git replace abcdef history/master

    【讨论】:

      猜你喜欢
      • 2017-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 1970-01-01
      • 2012-10-14
      相关资源
      最近更新 更多