我有两个git存储库:内部和外部。内部回购有我们的完整历史。从大约3周前开始,外部存储库有一个内部存储库快照的提交。从图形上看,它看起来像这样:
A01
|
A02
|
A03
|
A04 --> snapshot to B01
|
A05
|
A06 - A07
| |
A08 |
| /
A09 /
| /
| /
+
|
A10
|
A11
|
A12
我的问题是如何最好地将提交A05到A12合并到本地副本存储库B? (在将它们推向我们面向公众的回购之前,我将其内部压扁)
A和B是完全不相关的存储库(B不是作为A的克隆创建的;我们从提交A04获取了回购A的结帐副本并将它们检入新的回购B中)
所有这一切的扭曲(如果它不是真的,我会继续使用快照)是我有文件重命名。 Repo A包含重构提交,其中文件被重命名和移动。如果我只拍摄A12的快照并提交给B01,那么我不得不告诉Git如何在移动之前和之后关联文件(如Mercurial中的hg rename -A
);这些信息已经在Repo A的历史中,我不想重新创建它。
答案 0 :(得分:2)
其他人建议手动将已签出的版本复制到存储库B.您真正想要做的是 squash 提交A01
,A02
和{{1}转到A03
。这可确保您在提交回购B时不会疏忽。
现在,如果A和B在同一个回购中,这将很简单,但事实并非如此。幸运的是,只需在A:
的副本中添加B作为遥控器,就可以实现非常相似的功能B01
B已设置为远程~/A $ git remote add external ssh://path/to/B
~/A $ git fetch external
。它有一个完全独立的DAG,但它们位于同一个存储库中,所以现在你可以压缩提交。不幸的是,我想你必须知道你创建了哪个提交external
。可能有一些神秘的Git命令可以告诉你,但是很容易自己解决这个问题。对于此示例,提交为B01
。 (显然,这将是现实中的缩写。)现在壁球:
A04
此处,~/A $ git rebase --interactive A04 --onto external/master
指的是您的DAG中的external/master
。
在运行上述命令时出现的编辑器中,将每次提交时的操作更改为B01
。 (在Vim中,使用块模式很容易。)它应该如下所示:
squash
退出编辑器并允许Git应用更改。现在,您可以将更改推送到pick A03
squash A02
squash A01
到远程存储库。
答案 1 :(得分:1)
通过创建要签入的快照(例如,仅针对发行版或其他内容)启动单独的repo后,您应该计划在每次要更新该单独的repo时执行此过程,以便正确跟踪文件删除/重命名/等。情况:
git archive
对此有利).git/
,可能.gitignore
,.gitattributes
等等) - 但请注意,尚未提交这些更改:$ git clean -fdx $ git rm -r *
$ git add -A . $ git commit
我有许多软件包可以完成此操作(例如gcc
)以保留发布历史记录 - 生成的存储库比保留所有发布存档小得多。
或者,您可能会使用git bundle
,git merge
,git cherry-pick
,git rebase
和某些git format-patch
/ {{1}来找出一些复杂的方式} / git am
诡计做类似的事情,但其中许多依赖于两个存储库之间的一些近似共同历史,而你没有。这种程序的复杂性可能超过你可能想象的任何可能的好处。
答案 2 :(得分:0)
假设自拍摄快照后你没有对B做过任何更改,你真正想做的就是让B看起来像A的镜像副本。既然你提到它们是完全不相关的存储库,那么#34 ;我假设你的本地机器上有两个目录(每个目录一个)。由于您计划将这些更改压缩到一个提交中,我建议您只需将指向A(减去.git目录)的本地目录的内容复制到指向B的目录。执行git add --all .
,提交,然后推。