我正在学习git,但遇到了一个难题...
有两个项目不是我的:
- Delila
- Julio
背景
- Delila在很久以前从Julio分叉出来。
- Julio一直在快速发展。
- 我有一个在Delila中的功能,我想把它放到Julio中。
- 对于Julio的所有者而言,该功能没有意义,因为它不够通用(这就是为什么Delila的原始作者从未提供拉取请求的原因)。
- Delila显然不想要来自Julio的所有新东西,因此提供一个包含来自Julio的所有新东西的巨大拉取请求给Delila也不明智。
荒唐的方案
现在,我想从Delila中取出一个文件并将其放入Julio中,因为Julio包含了我需要的大量好东西,而Delila则包含了我真正需要的奇妙功能。
因此,实际上,我可以这样做:
- 将Julio分叉到一个我实际拥有的新项目中(我将称之为Benito)
- git clone Delila以获取旧代码
- git clone Benito以获取我fork的新代码
- 从包含Delila的目录中复制我需要的文件到Benito中
- 微调它,使其与周围的新内容一起工作,并将其添加到Benito中
- git commit Benito,git push它,然后喝上一杯应得的茶
但是茶味道很酸。我把别人的功劳归于自己(如果你查看该文件的历史记录,只会看到我),而且我失去了潜在有用的历史信息(为什么那个疯子要这样做...?)。
那么在这种情况下正确的做法是什么呢?
更新
感谢@djechlin,我已经尝试过这个问题,但我仍然无法解决它。在此,我通过本地创建两个存储库Julio和Delila来模拟该情况。所以,这是起始情况:
Julio
~/playing/Julio (master)
$ git log
commit f72960c18392d843d40adfd1c7ab943162005879
Author: xxxxx
Date: Tue Sep 24 08:46:50 2013 +0200
A change after Delila left the building
commit eca80d52acefcb02baae48e717bd8c2d98685c5e
Author: xxxxx
Date: Tue Sep 24 08:31:15 2013 +0200
initial commit from Julio
Delila
~/playing/Delila (master)
$ git log
commit 0e7c530246bc782dbf30fb4ac425e031d3626bbe
Author: xxxxx
Date: Tue Sep 24 08:39:06 2013 +0200
Added changes for Delila
commit eca80d52acefcb02baae48e717bd8c2d98685c5e
Author: xxxxx
Date: Tue Sep 24 08:31:15 2013 +0200
initial commit from Julio
你可以看到Delila已经从Julio分叉出来,并进行了一些更改。具体而言,我想保留的是“添加Delila更改”的提交。
现在,按照答案,在~/playing目录下执行以下操作:
~/playing
$ mkdir me
~/playing
$ cd me
~/playing/me
$ git clone ../Delila
Cloning into 'Delila'...
done.
~/playing/me
$ cd Delila
~/playing/me/Delila (master)
$ git remote rm origin
~/playing/me/Delila (master)
$ git filter-branch --subdirectory-filter someFolder -- --all
Rewrite 0e7c530246bc782dbf30fb4ac425e031d3626bbe (2/2)
Ref 'refs/heads/master' was rewritten
~/playing/me/Delila (master)
$ mkdir someFolder
~/playing/me/Delila (master)
$ mv * someFolder
mv: cannot move `someFolder' to `someFolder/someFolder'
现在,我不想要整个文件夹,所以我这样做:
~/playing/me/Delila (master)
$ git rm theNewFeature
rm 'theNewFeature'
~/playing/me/Delila (master)
$ git rm anotherFileFromJulio
rm 'anotherFileFromJulio'
这样做是否不正确?
回到答案:
~/playing/me/Delila (master)
$ git add .
~/playing/me/Delila (master)
$ git commit -m "filtered Delila"
[master b7fde89] filtered Delila
2 files changed, 0 insertions(+), 0 deletions(-)
rename anotherFileFromJulio => someFolder/anotherFileFromJulio (100%)
rename theNewFeature => someFolder/theNewFeature (100%)
现在我想要“分叉”Julio,因此我这样做:
~/playing/me
$ git clone ../Julio
Cloning into 'Julio'...
done.
~/playing/me
$ cd Julio
~/playing/me/Julio (master)
$ git remote rm origin
好的,回到答案中的步骤...
~/playing/me/Julio (master)
$ git remote add repo-A-branch ../Delila
~/playing/me/Julio (master)
$ git pull repo-A-branch master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 8 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
From ../Delila
* branch master -> FETCH_HEAD
Merge made by the 'recursive' strategy.
someFolder/theNewFeature | 1 +
1 file changed, 1 insertion(+)
create mode 100644 someFolder/theNewFeature
~/playing/me/Julio (master)
$ git remote rm repo-A-branch
那就是这样了,让我们来看一下我们移植的特殊功能的日志...
~/playing/me/Julio/someFolder (master)
$ git log theNewFeature
commit b7fde8940d761f7babe13d8b6cdfa12fe1685390
Author: xxxxx
Date: Tue Sep 24 09:01:43 2013 +0200
filtered Delila
叹气,那我做错了什么?历史记录去哪儿了?
git cherry-pick
进行改进。但是,如果没有进行完整的仓库合并,我不确定如何在两个模糊相关的仓库之间执行此操作。请记住,文件的历史记录是指提交,您正在尝试避免移植这些提交。 - djechlin