1

我有这个配置:

RepoA
  |-Dir1

RepoB

问题是 RepoB 被复制并修改了 Dir1。有没有办法在不丢失 RepoB 历史的情况下将 RepoB 合并到 RepoA 中?

4

1 回答 1

0

肯定有一种方法可以挽救 中的历史RepoB,如果理解正确,它代表了Dir1under的一个版本RepoA

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

  2. 接下来,我将同时指出RepoARepoB指向一个共同的祖先。如果RepoA有上游,则可以编辑RepoB's以指向同一上游。.git/config

  3. 然后我们将rescue分支推入RepoB上游,然后将其捡起。现在有了材料。git fetchRepoARepoA

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

具体场景,从头开始。在这个会话中,我们创建一个repo-aupstream. 在repo-a我们创建一个dir1/file. 然后我们创建一个新的 git reporepo-b作为dir1. 我们对file. 然后我们重写历史记录,以便将文件移动到dir/file并重播更改,我们在一个名为rescue. 我们upstream设置为远程repo-b并推rescue到那里。然后我们拉rescue入,在上面进行repo-arebase ,然后安装为。rescuemasterrescuemaster

注意:历史重写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,调用它repo-b,并将其初始化为 Git 存储库,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-bupstream

~/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使文件位于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分支及其对象:

~/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

从这里开始,它是 Git 101 材料。我们将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

~/repo-a$ git checkout master
Switched to branch 'master'
~/repo-a$ git reset --hard rescue
HEAD is now at 2546207 ghi
~/repo-a$ cat dir1/file 
abc
def
ghi

完毕。

于 2014-12-20T06:35:38.190 回答