我有这个配置:
RepoA
|-Dir1
RepoB
问题是RepoB被复制并修改了Dir1。有没有办法如何将RepoB合并到RepoA而不会在RepoB上丢失历史记录?
答案 0 :(得分:0)
肯定有一种方法可以拯救RepoB
中的历史记录,如果正确理解,则代表Dir1
下的RepoA
版本。
首先,我将首先在RepoB
中重写开发分支的历史记录,以便根据模式* -> Dir1\*
重命名所有文件。也就是说,我会进入最早的提交,将所有文件的git mv
执行到子目录中,然后重新设置其他所有文件。这对于git rebase --interactive
是可行的。我会为此创建一个RepoA
中不存在的分支。我们称之为rescue
分支。
接下来,我会将RepoA
和RepoB
都指向一个共同的祖先。如果RepoA
有上游,则可以编辑RepoB
的{{1}}以指向同一个上游。
然后我们将.git/config
中的rescue
分支推入上游,并在RepoB
中执行git fetch
来挑选它。 RepoA
现在有材料。
此时,在RepoA
中,我们可以选择RepoA
分支提交到开发分支。
具体方案,从头开始。在此会话中,我们创建了一个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
完成。