Git合并了两个重叠的存储库

时间:2012-07-31 13:33:11

标签: git

我有这个配置:

RepoA
  |-Dir1

RepoB

问题是RepoB被复制并修改了Dir1。有没有办法如何将RepoB合并到RepoA而不会在RepoB上丢失历史记录?

1 个答案:

答案 0 :(得分:0)

肯定有一种方法可以拯救RepoB中的历史记录,如果正确理解,则代表Dir1下的RepoA版本。

  1. 首先,我将首先在RepoB中重写开发分支的历史记录,以便根据模式* -> Dir1\*重命名所有文件。也就是说,我会进入最早的提交,将所有文件的git mv执行到子目录中,然后重新设置其他所有文件。这对于git rebase --interactive是可行的。我会为此创建一个RepoA中不存在的分支。我们称之为rescue分支。

  2. 接下来,我会将RepoARepoB都指向一个共同的祖先。如果RepoA有上游,则可以编辑RepoB的{​​{1}}以指向同一个上游。

  3. 然后我们将.git/config中的rescue分支推入上游,并在RepoB中执行git fetch来挑选它。 RepoA现在有材料。

  4. 此时,在RepoA中,我们可以选择RepoA分支提交到开发分支。

  5. 具体方案,从头开始。在此会话中,我们创建了一个rescue,它是从repo-a克隆的。在upstream我们创建了repo-a。然后我们创建一个新的git repo dir1/file作为repo-b的副本。我们对dir1进行了一些黑客攻击。然后我们重写历史记录,以便将文件移动到file并重播更改,然后我们在名为dir/file的分支中执行此操作。我们将rescue设为upstream的偏远地区,然后将repo-b推送到那里。然后,我们将rescue拉入rescue,在repo-a之上重新定位rescue,然后将master安装为rescue

    注意:使用一些手动命令攻击master中的历史记录重写。我首先硬重置到基本提交,做了rescue将文件移动到子目录,并修改了根提交。然后我在那之后挑选了下一个提交。实际上,我会做一个git mv,但这很难显示为记录的会话。

    git rebase --interactive <root-commit-sha>

    好的,现在出现了愚蠢的部分:有人复制~$ mkdir upstream ~$ mkdir repo-a ~$ cd upstream ~/upstream$ git init --bare Initialized empty Git repository in /home/kaz/upstream/ ~/upstream$ cd ../repo-a ~/repo-a$ git clone ../upstream . Cloning into '.'... done. warning: You appear to have cloned an empty repository. ~/repo-a$ mkdir dir1 ~/repo-a$ cd dir1 ~/repo-a/dir1$ cat > file abc def ~/repo-a/dir1$ git add file ~/repo-a/dir1$ git commit -m "file added" [master (root-commit) 1b5cdf9] file added 1 file changed, 2 insertions(+) create mode 100644 dir1/file ~/repo-a/dir1$ git push origin master Counting objects: 4, done. Writing objects: 100% (4/4), 252 bytes, done. Total 4 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (4/4), done. To /home/kaz/repo-a/../upstream * [new branch] master -> master ,称之为repo-a/dir1,并将其初始化为Git仓库,在版本控制和提交下添加repo-b

    file

    现在,同一个人开始使用~/repo-a/dir1$ cd ../.. ~$ cp -a repo-a/dir1 repo-b ~$ cd repo-b ~/repo-b$ git init Initialized empty Git repository in /home/kaz/repo-b/.git/ ~/repo-b$ git add file ~/repo-b$ git commit -m "repob" [master (root-commit) fe0c898] repob 1 file changed, 2 insertions(+) create mode 100644 file ,为其添加材料:

    file

    现在,这个人意识到,“哦,不,我在做什么!我希望在~/repo-b$ cat file abc def ~/repo-b$ cat >> file ghi ~/repo-b$ git diff diff --git a/file b/file index 5f5521f..8edb37e 100644 --- a/file +++ b/file @@ -1,2 +1,3 @@ abc def +ghi ~/repo-b$ git commit -a -m "ghi" [master 3e35a62] ghi 1 file changed, 1 insertion(+) repo-a下进行此更改。”

    第一步是将dir1连接到repo-b

    upstream

    现在,停止使用~/repo-b$ git remote add origin ../upstream ,然后切换到与master相同的rescue分支:

    master

    现在,重写~/repo-b$ git checkout -b rescue Switched to a new branch 'rescue' ~/repo-b$ git log commit 3e35a6216f8788cc7a58f7bb84a2dfaf8e47e720 Author: Kaz <kaz@stackoverflow.help.com> Date: Fri Dec 19 22:17:54 2014 -0800 ghi commit fe0c898b11124d0174e65b32fdcc956443446dcf Author: Kaz <kaz@stackoverflow.help.com> Date: Fri Dec 19 22:17:25 2014 -0800 repob 的历史记录,以便文件位于rescue下。首先,重置为root提交,然后重命名:

    dir1

    现在,我们在顶部挑选变化。在重命名之后,对~/repo-b$ git reset --hard fe0c898b11124d0174e65b32fdcc956443446dcf HEAD is now at fe0c898 repob ~/repo-b$ mkdir dir1 ~/repo-b$ git mv file dir1 ~/repo-b$ git commit -a --amend -m "repob" [rescue e3a6c19] repob 1 file changed, 2 insertions(+) create mode 100644 dir1/file 进行了很好的修补:

    dir1/file

    好的,现在我们将救援包推到~/repo-b$ git cherry-pick 3e35a6216f8788cc7a58f7bb84a2dfaf8e47e720 [rescue 7f21bf5] ghi 1 file changed, 1 insertion(+) ~/repo-b$ ls dir1 ~/repo-b$ cat dir1/file abc def ghi

    ../upstream

    再次关闭~/repo-b$ git push origin rescue Counting objects: 8, done. Delta compression using up to 4 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (8/8), 507 bytes, done. Total 8 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (8/8), done. To ../upstream * [new branch] rescue -> rescue 。在那里,我们执行repo-a来引入git fetch分支及其对象:

    rescue

    从这里开始,它是Git 101材料。我们在~/repo-b$ cd .. ~$ cd repo-a ~/repo-a$ git fetch remote: Counting objects: 8, done. remote: Compressing objects: 100% (2/2), done. remote: Total 8 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (8/8), done. From /home/kaz/repo-a/../upstream * [new branch] rescue -> origin/rescue 之上重新定位rescue分支。

    master

    然后我们切换回~/repo-a$ git checkout rescue Branch rescue set up to track remote branch rescue from origin. Switched to a new branch 'rescue' ~/repo-a$ git rebase master First, rewinding head to replay your work on top of it... Applying: ghi ~/repo-a$ ls dir1 ~/repo-a$ cat dir1/file abc def ghi ~/repo-a$ # YAY! ,并将其快进到master

    rescue

    完成。