use*_*119 20 git merge git-merge
我有一个git仓库mainline(相当于master)和一些本地功能分支.例如:
$ git branch
* mainline
  feature1
  feature2
  feature3
当我执行以下操作时,我能够将功能分支中的所有编辑内容合并为一个提交到mainline:
$ git checkout mainline
$ git pull
$ git checkout feature1
$ git rebase mainline
$ git checkout mainline
$ git merge --squash feature1
$ git commit
$ git push
我的问题是,在这一点上,当我尝试删除feature1分支时,它告诉我它没有完全合并:
$ git branch -d feature1
error: The branch 'feature1' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature1'.
是什么导致这个错误?我以为git merge --squash feature1合并feature1了mainline.
tor*_*rek 44
这是因为Git不知道squash merge是"等同于"各种特定于分支的提交.您必须强行删除分支,git branch -D而不是git branch -d.
(其余部分仅仅是为什么会出现这种情况.)
让我们绘制(部分)提交图(这一步适用于Git中的许多内容......).事实上,让我们再退一步,以便我们在你之前开始git rebase,有这样的事情:
...--o--o--o     <-- mainline
      \
       A--B--C   <-- feature1
分支名称(如mainline或feature1)仅指向一个特定提交.该提交指回(向左)到先前的提交,依此类推,并且这些反向指针构成了实际的分支.
提交的最上一行,都在o这里调用,有点无聊,所以我们没有给他们字母.提交的下排A-B-C,都只是分支feature1.  C是最新的这样的提交; 它导致回到B,导致回到A,这导致一个无聊的o提交.(顺便说一句:最左边的o提交,以及该...部分中所有早期的提交,都在两个分支上.)
当你运行时git rebase,三个A-B-C提交被复制到附加到提示的新提交mainline,给我们:
...--o--o--o            <-- mainline
      \     \
       \     A'-B'-C'   <-- feature1
        \
         A--B--C       [old feature1, now abandoned]
新A'-B'-C'提交与原始提交大致相同,但它们在图中移动.(注意,这三种无聊o提交上两个分支了.)放弃了Git通常不会原有三种方式都在拷贝比较原件.(如果原件可以通过其他名称访问 - feature1例如附加到旧的分支 - 例如-Git 可以解决这个问题,至少在大多数情况下.Git如何计算出这一点的确切细节在这里并不是特别重要. )
无论如何,现在你继续跑git checkout mainline; git merge --squash feature1.这使得一个新的提交是三个或多个提交的"压缩副本" feature1.我将停止绘制旧的废弃的,并S为Squash 调用新的壁球:
...--o--o--o--S         <-- mainline
            \
             A'-B'-C'   <-- feature1
当你要求Git删除时feature1,它会执行安全检查:"已feature1合并到mainline?" 这个"合并到"测试完全基于图形连接.该名称mainline指向提交S; 将S点提交回第一个无聊的o提交,这会导致更多无聊的o提交.提交C',提示feature1,是不可达到的S:我们不允许向右移动,只向左移动.
将此与"正常"合并进行对比M:
...--o--o--o---------M   <-- mainline
            \       /
             A'-B'-C'    <-- feature1
使用相同的测试 - "提示是否feature1可以从提示提交mainline?" - 答案现在是肯定的,因为提交M有一个左下角提交链接C'.(C'在Git内部说法中,Commit 是合并提交的第二个父级M.)
但是,由于壁球合并实际上并不合并,所以从S后面没有连接C'.
此外,Git不会甚至尝试,看看是否S是"同" A',B'或C'.但是,如果确实如此,它会说"不一样",因为S它只与所有三次提交的总和相同.获得S匹配压缩提交的唯一方法是只有一个这样的提交(在这种情况下,首先不需要压缩).
Rus*_*Kie 10
实际上,您可以确定和删除压缩合并的分支,尽管这很重要。
git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base master $branch) && [[ $(git cherry master $(git commit-tree $(git rev-parse $branch\^{tree}) -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done
为了确定一个分支是否被压缩合并, git-delete-squashed 使用git commit-tree创建一个临时的悬空压缩提交。然后它使用git cherry检查压缩的提交是否已经应用到 master。如果是,则删除该分支。
所有学分归 Teddy Katz,https://github.com/not-an-aardvark/git-delete-squashed