git:混合分支 - 如何清理

时间:2017-05-08 20:16:30

标签: git

我在两个分支机构工作,混淆了一切。用于分支A的一些变化在分支B中,而在相反的情况下。某些提交包含对正确分支的更改以及同时错误的更改。我用这种混合做了几次提交。

之后我在正确的分支中再次进行了更改。 所以我最终得到了正确分支中的所有更改,但每个更改也属于另一个分支的旧更改。 然后对于分支A我推了,对于分支B我已经做了拉请求。

问题1:如何从每个分支中删除不属于那里的更改? 我确切地知道我需要将分支中的哪些文件恢复到原始状态。

问题2:如何更改已经提出的拉取请求?

2 个答案:

答案 0 :(得分:1)

为了将来参考,在推送之前清理它会更安全。此时,您有两种选择:

  • 您可以创建新分支(使用新名称)并将所需的更改迁移到每个分支。现有的分支机构最终将被放弃。

  • 您可以“重写历史记录”来修复现有分支。获取/取消现有分支的任何其他人都必须执行恢复过程(请参阅git rebase文档中的“从上游rebase中恢复”以获取有关此问题的一般性讨论。)

我会假设第一个选项写出这个程序,因为它在某些方面更安全。如果您想使用历史记录重写,我会给出一些关于如何调整过程的注释。我将展示如何执行branchAbranchB的过程基本相同。我假设分支是从master创建的(因此,如果没有,则用适当的“父分支”替换对master的所有引用)。

查看现有分支。

git checkout branchA

假设您不希望将新分支移动到master的提示,则需要找到分支点。为简化说明,我们在此处创建一个临时标记(虽然从技术上讲,您可以使用SHA1 ID代替此提交。)

所以你有

x --- A --- x <--(master)
       \
        A1 --- B1 --- AB1 --- A2 <--(branchA)

,您需要找到A。如果您知道branchA分割后master上有4个提交(在此示例中),则可以说

git tag rootA branchA~4

如果您不知道该号码,您可以从GUI前端或git log --graph master branchA(如果提交历史记录足够小以至于这是实用的)进行观察,或者如果不是:

git rev-list master..branchA

输出的最后一行是分支上第一次提交的SHA1,所以假设你是31337c0d3

git tag rootA 31337c0d3^

(注意最后的^)。

你现在应该有这样或那样的方式

   [rootA]
      |
x --- A --- x <--(master)
       \
        A1 --- B1 --- AB1 --- A2 <--(branchA)

现在创建新分支(但如果使用“history rewrite”选项,则可以跳过此步骤。)

git checkout -b new_branchA

现在开始一个互动的变基会议

git rebase -i --onto rootA master

您将获得一个带有“待办事项”列表的文本编辑器,每行代表一次提交。

对于属于branchA的提交,保持行不变(pick命令)

对于属于branchB的提交 - 考虑到您已在branchB上进行了这些更改 - 您只需将命令从pick更改为drop

如果任何提交混合了更改(某些提交属于branchA,其他提交属于branchB),请将命令从pick更改为edit

保存并退出文本编辑器,git将启动rebase。如果您使用edit标记了任何提交,那么git将暂停并提示您进行编辑,然后告诉它恢复rebase。

当rebase完成后你将拥有

   [rootA]
      |
x --- A --- x <--(master)
      |\
      | A1 --- B1 --- AB1 --- A2 <--(branchA)
      \
       A1' --- Ab1' --- A2' <--(new_branchA)

(其中Ab1'AB1的已修改替代品,其中仅保留了BranchA的更改。

如果您将此作为历史记录重写,那么branchA将指向A2',当然不会有new_branchA

您可以清理临时标签。

git tag --delete rootA

除非您进行了重写历史记录,否则您不再需要旧的branchA

git branch --delete branchA

最后,您可以推送到远程

git push

(在历史重写的情况下,需要-f选项)。

答案 1 :(得分:0)

如果您尚未推出这些分支,您可以:

  • 创建分支tmpAtmpB(例如来自origin/Aorigin/B
  • git cherry-pick您需要从AtmpA,从BtmpB的提交;如果您需要编辑提交,请使用选项--no-commit,然后git reset清除索引,然后git add -p只添加想要的更改,然后提交结果
  • 将这些本地分支A重置为tmpAgit branch -f A tmpA),B也是如此。
  • 删除tmpAtmpB