Git 反复合并壁球 [英] Git merge squash repeatedly

查看:24
本文介绍了Git 反复合并壁球的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 git 中有两个带有二进制文件的分支 - 一个开发"和一个稳定".在我想将这些文件发布"到稳定分支之前,开发分支可以对这些文件进行多次更改(如果相关,稳定分支会重命名这些文件).

我可以做一个普通的合并,这工作正常,但保留了太多的历史记录 - 当拉取稳定"分支时,所有来自开发"分支的中间提交也被拉取(因为它们是父提交).但是我们谈论的是没有任何合理合并策略的二进制文件(除了他们/我们的),因此开发分支上文件的实际历史是无用的.当我拉稳定"分支时,我得到了这个:

<前>X-------------------G 稳定//a---b---c---d---e---f---g 发展

因为 G 在开发分支中有一个父级,所以我在我的存储库中获得了开发分支的整个历史(c、d、e、f 和 g 的数据对象),我对此不感兴趣(X 是与 b 相同,但应用了一些文件重命名).

所以我尝试将 git merge --squash 从开发分支更改为稳定分支.第一次这样的合并和提交成功,结果如预期(提交消息中的更改日志很好,与开发分支无关):

 X-------------------G 稳定/a---b---c---d---e---f---g 开发

在我拉出这个压扁的稳定分支后,我在我的存储库中得到了它,这就是我想要的:

<前>a---b---X---G

但是第二次合并失败了(因为 git 无法知道我已经合并了多少并感到困惑).

  • 是否有可能以某种方式记录合并,而不产生与两个父项的合并提交"?
  • 或者,是否可以告诉 git 只合并某个范围"的修订版本,就像在 SVN 中一样?
  • 或者,是否可以在拉取时无需从另一个分支下载所有引用的情况下进行正常合并?
  • 或者我应该为有问题的文件提供自定义合并驱动程序,只需将他们的"版本重命名为我们的",从而解决冲突?我仍然担心 --squash 将始终尝试合并整个历史记录,直到共同的父级,仅解决我的一半问题.

更新:重新定位

如果我正确理解变基,我会得到这个:

<前>X 稳定/a---b---c---d---e---f---g 发展

这为我提供了我不感兴趣的所有数据 (c, d, e, f) 并且作为奖励,我将丢失 b 是分支中的稳定版本的信息.

每个开发版本都会增加大约 5MB 的存储库大小(重新打包整个存储库只会缩小大约 10%),稳定"分支几乎是免费的(数据已经存在).我想从稳定分支中提取一个新的修订版以仅提取新的 5MB,而是从 X 更新到 G 下载 25MB,因为我不知何故不能说我不关心 c、d 的内容, e 和 f.

解决方案

开始

 X 稳定/a---b---c---d---e---f---g 发展

您可以使用以下步骤将最后一次提交从开发分支复制到稳定分支:

git checkout development@{0} # 从development"中获取工作树,分离 HEADgit reset --soft stable # 在稳定"上重新定位分离的 HEADgit commit # 输入适当的提交信息git branch temp # 在 HEAD 创建一个临时分支temp"git checkout temp # 进入新的临时分支git branch -M stable # 将temp"重命名为stable"

所以你最终得到:

 X-------------------G 稳定/a---b---c---d---e---f---g 发展

如果您继续从事开发"工作,例如

 X-------------------G 稳定/a---b---c---d---e---f---g---h---i---j 发展

你可以重复上面相同的 git 命令,你会得到:

 X-----------G-----------J 稳定/a---b---c---d---e---f---g---h---i---j 发展

I'm trying to have two branches with binary files in git - one "development" and one "stable". The development branch can have several changes of these files before I want to "release" them to the stable branch (and the stable branch has those files renamed, in case that's relevant).

I could do a normal merge, this works fine, but preserves too much history - when pulling the "stable" branch, all intermediate commits from the "development" branch are pulled as well (because they're parent commits). But we're talking about binary files that don't have any sensible merging strategy (except theirs/ours), so the actual history of the files on the development branch is useless. When I pull the "stable" branch, I get this:

          X-------------------G stable
         /                   /
    a---b---c---d---e---f---g development

Because G has a parent in the development branch, I get the whole history of the development branch (data objects for c, d, e, f and g) in my repository, which I'm not interested in (X is the same as b, with some file renaming applied).

So I tried to git merge --squash changes from the development branch to the stable branch. The first such merge and commit went OK, the results were as expected (nice change log in the commit message, no relation to the development branch):

          X-------------------G stable
         /                   
    a---b---c---d---e---f---g development

After I pull this squashed stable branch, I get this in my repository, which is what I want:

a---b---X---G

But the second merge failed (because git had no way to know how much I merged already and got confused).

  • Is it possible to somehow record the merge, without producing a "merge commit" with two parents?
  • Or, is it possible to tell git to merge only a certain "range" of revisions, like in SVN?
  • Or, is it possible to do a normal merge without having to download all refs from the other branch when pulling?
  • Or should I provide a custom merge driver for the files in question, that simply renames "their" version to "our", thereby resolving the conflicts? I'm still afraid that --squash will always try to merge the whole history, up to the common parent, solving only half of my problem.

Update: rebasing

If I understand rebasing correctly, I'll end up with this:

                              X stable
                             /
    a---b---c---d---e---f---g development

Which gets me all the data I'm not interested in (c, d, e, f) and as a bonus, I'll loose the information that b was a stable version in the branch.

Each development revision adds about 5MB to the repository size (and repacking the whole repo shrinks it only about 10%), the "stable" branch comes almost for free (the data is already there). I want pulling a single new revision from the stable branch to pull only the new 5MB, but instead updating from X to G downloads 25MB, because I'm somehow not able to say that I don't care about the contents of c, d, e and f.

解决方案

Starting with

      X stable
     /                   
a---b---c---d---e---f---g development

You can use the following steps to copy the last commit from your development branch to your stable branch:

git checkout development@{0}  # get working tree from "development", detach HEAD
git reset --soft stable  # reposition detached HEAD on "stable"
git commit  # enter the appropriate commit message
git branch temp  # create a temporary branch "temp" at HEAD
git checkout temp  # get on the new temporary branch
git branch -M stable  # rename "temp" to "stable"

so you end up with:

      X-------------------G stable
     /                   
a---b---c---d---e---f---g development

If you continue work on "development", e.g.,

      X-------------------G stable
     /                   
a---b---c---d---e---f---g---h---i---j development

you can repeat the same git commands as above and you will end up with:

      X-------------------G-----------J stable
     /                   
a---b---c---d---e---f---g---h---i---j development

这篇关于Git 反复合并壁球的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆