1

TL;博士; 我想要一种方法告诉 git“master 有一个新版本,看起来与功能 A 的尖端完全相同,但没有历史记录”。

有没有办法做到这一点?

[更新:我现在有一个最小化这个问题的工作流程,但我仍然想知道如何告诉 git 执行以下操作:-

提交对分支 X 的单个更改,以使所有文件和文件夹与分支 Y 尖端的文件和文件夹匹配。这可能吗?]


背后的故事

我们通常避免从功能分支分支......但在这种情况下必须这样做。这是我们尝试做的:-

master   o-----------------o---------------o       
          \               /[squash]       /
feature A  o-o-o-o-o-o-o-o               / [squash] -- too many conflicts
                  \                     /
feature B          o-o-o-o-------------o

由于各种原因,我们总是挤到主人身上。但是由于特性 B 与特性 A 有很多共同的变化,第二个 squish 有很多合并冲突。

我试过这个...

master   o-----------------o----------------o       
          \               /[squash]        / [squash]  -- same set of conflicts!!
feature A  o-o-o-o-o-o-o-o----------------o
                  \                      / (merge) -- easy
feature B          o-o-o-o--------------o

(合并)很容易,并且功能 A 与我希望 master 拥有的文件集完全相同(因为功能 A 和 master 在合并到 master 后具有相同的文件)。这种合并很容易,因为 Git 知道只有在功能 B 分支后才需要解决冲突。

那时我想将现在合并的功能 A 分支提交给 master。但是我遇到了我试图避免的同样的冲突。

功能 A 具有我想要的所有更改...所以我可以检查主和功能 A 并将所有文件复制到主控中,然后提交。事实上这就是我最终做的......但肯定有办法用 git 做到这一点?!?

我尝试从masterfeature A生成一个二进制补丁,然后应用它。

 git diff --binary master featureA > patch
 git apply patch 

这因“补丁不适用”错误而失败。

我尝试了其他各种合并尝试……所有这些都导致我不得不解决我已经重新解决的所有相同的合并冲突。


合并是从功能 B 到主控的痛苦的原因是,在功能 B 分支之前功能 A 中更改的文件在提交之前由功能 A 进一步更改。这意味着 Git 将这些文件视为功能 B 中的更改,但它们与功能 A 中提交的文件不同,因此需要合并。

在提交之前在 master 上重新设置功能 B 意味着您必须再次执行您未触及的文件的合并。

4

2 回答 2

2

解决 Git 问题的方法不止一种,但最常见的方法之一就是在尝试合并之前简单地将分支 B 重新设置到主分支上。

假设 X 是分支 A 和 B 之间共享的共同祖先提交。那么

  1. 将 B 变基到 master

    git rebase --onto master X B
    

    这将在 X 之后并导致 B 的所有提交,并将它们重新应用到主分支之上。您可能仍然需要解决冲突,但您将在较小的块中解决它们,因为您会一一重新应用提交。

  2. 接下来,您可以使用软重置压缩分支 B,然后进行提交(请注意,这不是压缩 B 的唯一方法):

    git reset --soft X
    git commit -m "Squashing B"
    

    请注意,您可以颠倒第 1 步和第 2 步。唯一的区别是,通过首先压缩 B,您最终将不得不在 rebase 之后再次解决所有冲突。

  3. 将B合并到master中,

    git checkout master
    git merge B
    

作为上述步骤 #2 和 #3 的替代方法,如果您执行了步骤 #1,那么您可以使用git merge --squashsquash 和合并分支 B,

git checkout master
git merge --squash B
git commit -m "Squashed and merged B"
于 2014-06-23T05:15:59.987 回答
0

原始海报说:

(合并)很容易,并且功能 A 与我希望 master 拥有的文件集完全相同(因为功能 A 和 master 在合并到 master 后具有相同的文件)。

同样,正如我在评论中指出的那样,这没什么意义,而且您没有列出导致结果的命令序列。

但是,我将仅根据您的这个问题回答您的问题,而忽略所有其他不清楚的信息(强调我的):

提交对分支 X 的单个更改,以使所有文件和文件夹与分支 Y 顶端的文件和文件夹匹配。这可能吗?

与“我们的”战略和壁球合并

您可以通过先将 X 合并到 Y 来使分支 X 匹配 Y,但使用--strategy oursor-s ours选项忽略来自 X 的所有更改。然后在使用时将 Y 合并回 X(快进合并)--squash

git checkout Y
git merge --strategy ours X

# Verify that Y is unchanged
git diff Y^

git checkout X
git merge --squash Y
git commit

# Verify that X matches Y
git diff Y

文档

来自官方 git-merge(1) 手册页

合并策略

ours

这解决了任意数量的头,但合并的结果树始终是当前分支头的树,有效地忽略了所有其他分支的所有更改。它旨在用于取代分支的旧开发历史。

以下是相关文档--squash

选项

--squash

生成工作树和索引状态,就好像发生了真正的合并(合并信息除外),但实际上不进行提交或移动 HEAD,也不记录$GIT_DIR/MERGE_HEAD以导致下一个git commit命令创建合并提交。这允许您在当前分支之上创建一个提交,其效果与合并另一个分支相同(或者在章鱼的情况下更多)。

于 2014-06-24T06:06:46.963 回答