合并到第一个分支后合并分支的分支在合并到主分支时被压扁

Mik*_*ike 66 git squash arcanist

这是我在工作中经常处理的工作流程.

git checkout -b feature_branch
# Do some development
git add .
git commit
git push origin feature_branch
Run Code Online (Sandbox Code Playgroud)

此时,我的同事们正在审查功能部门,但我希望继续开发其他依赖的功能feature_branch.所以feature_branch在审查中......

git checkout feature_branch
git checkout -b dependent_branch
# Do some more development
git add .
git commit
Run Code Online (Sandbox Code Playgroud)

现在我做了一些更改以响应feature_branch上的代码审查

git checkout feature_branch
# Do review fixes
git add .
git commit
git checkout dependent_branch
git merge feature_branch
Run Code Online (Sandbox Code Playgroud)

现在这是我们遇到问题的地方.我们在master上有一个squash策略,这意味着合并到master中的功能分支必须压缩成一个提交.

git checkout feature_branch
git log # Look for hash at beginning of branch
git rebase -i  first_hash_of_branch # Squash feature_branch into a single commit
git merge master
Run Code Online (Sandbox Code Playgroud)

一切都很酷,除了dependent_branch.当我尝试将依赖分支重新绑定到master或尝试将master合并到其中时,git会被重写/压缩的历史所困惑,并且基本上将每个单独的更改标记depedendent_branch为冲突.这是一个PITA,通过并基本上重新做或去冲突所有的变化dependent_branch.这有什么解决方案吗?有时候,我会手动创建一个补丁并将其应用到一个新的主分支上,但是如果与它有任何真正的冲突,那就更难以修复了.

git checkout dependent_branch
git diff > ~/Desktop/dependent_branch.diff
git checkout master
git checkout -b new_dependent_branch
patch -p1 < ~/Desktop/dependent_branch.diff
# Pray for a clean apply.
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?我知道这是因为壁球期间重写的历史,但这是我无法改变的要求.什么是最好的解决方案/解决方法?我能做些什么吗?或者是否有更快的方法来完成手动创建差异所涉及的所有步骤?

jos*_*ing 85

一点为什么会发生这种情况:

在功能分支合并之后,我将O成为"原始主人"并FB成为"新主人":

feature_branch看起来像:

O - A - B - C 
Run Code Online (Sandbox Code Playgroud)

dependent_feature 除此之外还有一些额外的提交:

O - A - B - C - D - E - F
Run Code Online (Sandbox Code Playgroud)

您将原始功能分支合并为主分区并将其压缩,为您提供:

O - FB
Run Code Online (Sandbox Code Playgroud)

现在,当你尝试重新定义依赖分支时,git将试图找出这些分支之间的共同祖先.虽然它本来是这样的C,如果你没有压缩提交,git反而认为O是共同的祖先.其结果是,Git是试图重播A,B以及C它们已经包含FB了,你会得到一堆的冲突.

因此,您无法真正依赖典型的rebase命令,并且必须通过提供--onto参数来更明确地指出它:

git rebase --onto master HEAD~3  # instruct git to replay only the last
                                 # 3 commits, D E and F, onto master.
Run Code Online (Sandbox Code Playgroud)

HEAD~3根据需要修改分支的参数,您不必处理任何冗余的冲突解决方案.

一些替代语法,如果您不喜欢指定范围并且尚未删除原始功能分支:

git rebase --onto master feature_branch dependent_feature

                                 # replay all commits, starting at feature_branch
                                 # exclusive, through dependent_feature inclusive 
                                 # onto master
Run Code Online (Sandbox Code Playgroud)

  • --onto只是让您*更具选择性*关于要重播到分支上的提交。默认情况下,git尝试“找出”应该重播的提交。当使用--onto时,您明确指示git重播*一定范围的提交*。在我的示例中,如果不使用--onto,则最终会出现O-FB-A-B-C-D-E-F以及众多合并冲突的情况,因为FB和A-B-C包含相同的更改。通过使用--onto并指定最后3个提交,您将得到O-FB-D-E-F,这是原始请求者所希望的。 (3认同)