我有这个配置:
RepoA
|-Dir1
RepoB
问题是 RepoB 被复制并修改了 Dir1。有没有办法在不丢失 RepoB 历史的情况下将 RepoB 合并到 RepoA 中?
我有这个配置:
RepoA
|-Dir1
RepoB
问题是 RepoB 被复制并修改了 Dir1。有没有办法在不丢失 RepoB 历史的情况下将 RepoB 合并到 RepoA 中?
肯定有一种方法可以挽救 中的历史RepoB
,如果理解正确,它代表了Dir1
under的一个版本RepoA
。
首先,我将首先重写开发分支的历史记录,RepoB
以便根据模式重命名所有文件* -> Dir1\*
。也就是说,我会去最早的提交,将git mv
所有文件中的一个执行到子目录中,然后对其他所有内容进行rebase。这是可行的git rebase --interactive
。我会为此创建一个在RepoA
. 让我们称之为rescue
分支。
接下来,我将同时指出RepoA
和RepoB
指向一个共同的祖先。如果RepoA
有上游,则可以编辑RepoB
's以指向同一上游。.git/config
然后我们将rescue
分支推入RepoB
上游,然后将其捡起。现在有了材料。git fetch
RepoA
RepoA
此时,在 中RepoA
,我们可以挑选rescue
分支提交到开发分支。
具体场景,从头开始。在这个会话中,我们创建一个repo-a
从upstream
. 在repo-a
我们创建一个dir1/file
. 然后我们创建一个新的 git reporepo-b
作为dir1
. 我们对file
. 然后我们重写历史记录,以便将文件移动到dir/file
并重播更改,我们在一个名为rescue
. 我们upstream
设置为远程repo-b
并推rescue
到那里。然后我们拉rescue
入,在上面进行repo-a
rebase ,然后安装为。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
,调用它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-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
使文件位于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
完毕。