git仅合并从一个存储库到另一个存储库的最近更改,这是一个不相关的快照(不是克隆)

时间:2015-06-10 16:50:03

标签: git merge

我有两个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的历史中,我不想重新创建它。

3 个答案:

答案 0 :(得分:2)

其他人建议手动将已签出的版本复制到存储库B.您真正想要做的是 squash 提交A01A02和{{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时执行此过程,以便正确跟踪文件删除/重命名/等。情况:

  1. 在真实仓库中创建快照(git archive对此有利)
  2. 在您的“发布”回购中,删除工作副本中的所有内容(仅留下.git/,可能.gitignore.gitattributes等等) - 但请注意,尚未提交这些更改
  3. $ git clean -fdx
    $ git rm -r *
    
    1. 解压缩快照
    2. 提交新版本
    3. $ git add -A .
      $ git commit
      

      我有许多软件包可以完成此操作(例如gcc)以保留发布历史记录 - 生成的存储库比保留所有发布存档小得多。

      或者,您可能会使用git bundlegit mergegit cherry-pickgit rebase和某些git format-patch / {{1}来找出一些复杂的方式} / git am诡计做类似的事情,但其中许多依赖于两个存储库之间的一些近似共同历史,而你没有。这种程序的复杂性可能超过你可能想象的任何可能的好处。

答案 2 :(得分:0)

假设自拍摄快照后你没有对B做过任何更改,你真正想做的就是让B看起来像A的镜像副本。既然你提到它们是完全不相关的存储库,那么#34 ;我假设你的本地机器上有两个目录(每个目录一个)。由于您计划将这些更改压缩到一个提交中,我建议您只需将指向A(减去.git目录)的本地目录的内容复制到指向B的目录。执行git add --all .,提交,然后推。