如何使用git merge --squash?


1207

我有一个远程Git服务器,这是我要执行的方案:

  • 对于每个错误/功能,我创建一个不同的Git分支

  • 我继续使用非官方的Git消息在该Git分支中提交代码

  • 在顶级存储库中,我们必须使用官方Git消息对一个错误进行一次提交

那么,如何将我的分支合并到远程分支,以便他们对所有签入仅获得一次提交(我什至想为此提供提交消息)?


1
我不确定我是否完全理解您,但是您可能需要“章鱼合并”。
MatrixFrog 2011年

26
我通常使用git rebase -i将所有提交折叠为一个提交,然后重新写入提交消息。然后,我将其发送到上游。
爱德华·福尔克

17
git merge --squash一口气在命令行上完成所有操作,您只是希望它能起作用。git rebase -i调出一个编辑器,让您微调基准。它的速度较慢,但​​是您可以看到自己在做什么。此外,rebase和merge之间也存在差异,有些差异涉及到注释中。
爱德华·福尔克

4
所有这些答案的问题是您必须在本地master分支上并运行merge --squash命令...我想从功能分支而不是master分支上运行merge --squash。完成后,我可以将功能分支推送到远程并提交PR,这可能吗?
亚历山大·米尔斯

2
@AlexanderMills,我认为您只需要第二个功能分支(从master分支克隆)。执行merge --squash从旧到新,然后合并新的分支掌握。旧分支已过时。
Gyromite

Answers:


1997

假设您的错误修复分支被调用,bugfix并且您想将其合并为master

git checkout master
git merge --squash bugfix
git commit

这将从bugfix分支中获取所有提交,将它们压缩为1个提交,并将其与master分支合并。


说明

git checkout master

切换到您的master分支。

git merge --squash bugfix

bugfix分支获取所有提交,并将其与当前分支合并。

git commit

根据合并的更改创建一个提交。

省略-m参数可以使您在最终提交之前修改提交的消息草稿,其中包含来自被压缩的提交的每条消息。


222
如果要保留对旧提交消息的引用,则可以编写git commit(不带-m参数),并且可以修改包含已压缩的所有提交消息的草稿提交消息。
亚历克斯

12
您可以git commit --amend -m '...'稍后再做。
Janusz Lenar 2014年

19
如果发生合并冲突并且您解决了这些冲突,git commit将不再显示有用的提交消息,其中包含您压缩的所有提交消息。在这种情况下,请尝试git commit --file .git/SQUASH_MSG(通过stackoverflow.com/a/11230783/923560)。
阿卜杜勒

23
请记住,默认情况下壁球会将提交归于壁球。为了保留原始作者,您需要像这样明确指定它:git commit -a --author="Author" --message="Issue title #id"
令人讨厌的

5
git merge --squash允许您在当前分支之上创建一个提交,其作用与合并另一个分支相同。但这不会产生合并记录,这意味着您的拉取请求不会有任何变化,但不会被标记为已合并!因此,您只需要删除该分支即可完成。
am0wa

129

最终为我解决的是一条评论,显示:

git checkout main
git merge --squash feature

等价于:

git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .

当我想合并具有105(!!)个提交的功能分支并将它们全部压缩为一个时,我不想这样做,git rebase -i origin/master因为我需要分别解决每个中间提交(或至少是那些中间提交)的合并冲突git无法弄清楚自己)。使用git merge --squash可以得到想要合并整个功能分支的单个提交的结果。而且,我最多只需要执行一次手动冲突解决。


74
我强烈建议先在功能分支中执行合并,git merge master然后再git merge --squash feature在master分支中执行。
dotancohen

8
@dotancohen抱歉,打乱了一条旧评论:)在git merge --squash feature从master分支执行之前,合并到feature分支会获得什么?
bitsmack

56
您想先将master合并到Feature分支中,然后在Feature分支中处理所有手动修复。这也使您可以运行测试并确保功能分支正常运行。然后,可以确保可以将功能分支自动合并到master。
丹·科恩

4
@dankohn我建议您将以上评论中的解释添加到您的答案中。
贡特伯特2015年

3
@bitsmack:您将首先将master合并为功能。这使您有机会在将功能部件合并到母版之前解决功能部件上的冲突
Mike

97

您要与壁球选项合并。那就是如果您想一次做一个分支。

git merge --squash feature1

如果要在一次提交的同时合并所有分支,请首先以交互方式进行变基并压扁每个功能,然后章鱼合并:

git checkout feature1
git rebase -i master

压入一个提交,然后重复其他功能。

git checkout master
git merge feature1 feature2 feature3 ...

最后的合并是“章鱼合并”,因为它一次合并了许多分支。

希望这可以帮助


3
你为什么要下基地?
Umair A.

12
@UmairAshraf这是一个交互式的基础,可让您选择在分支机构内进行壁球。
andho

1
变基是个坏主意。不要重新建立已发布的提交内容
Sebi2020

1
@ Sebi2020 git merge --squash将以比交互式重新基准更糟糕的方式重新基准已发布的提交。交互式基础库(在功能分支上)几乎没有不良影响。
xiix

1
@xiix仅当您使用功能分支时才适用。这不是您可以做的假设。我建议阅读与在Git-SCM上重新基础相关的页面。它指出“ 不要对存储库外部存在的提交进行重新基准设置,否则人们可能会基于它们进行工作。 ”并且如果您不确定别人是否已经基于已发布的提交进行工作(由于分散性,您将无法知道这些信息) git的性质),您不应该这样做。
Sebi2020 '19

23

如果您已经git merge bugfix开启main,可以使用以下方法将合并提交压缩为一个:

git reset --soft HEAD^1
git commit

git reset --soft HEAD^1似乎撤销了合并之前执行的最后一次提交,至少在合并是快进的情况下如此。
杰斯珀·马蒂森

@JesperMatthiesen在快速转发的情况下,您不会获得合并提交,因此您可以这样做git reset --soft HEAD^<number-of-commits-to-squash>
qwertzguy

这有助于我在下游合并之后将所有内容压缩为单个提交。
killjoy

18

通过自定义提交合并newFeature分支master

git merge --squash newFeature && git commit -m 'Your custom commit message';

如果相反,您会

git merge --squash newFeature && git commit

您将收到一条提交消息,其中将包含newFeature您可以自定义的所有分支提交。

我在这里详细解释:https : //youtu.be/FQNAIacelT4


10

我知道这个问题不是专门针对Github的,但是由于Github的使用如此广泛,这是我一直在寻找的答案,因此我将在这里分享。

Github可以执行南瓜合并,具体取决于为存储库启用的合并选项。

如果启用了南瓜合并,则“压缩并合并”选项应出现在“合并”按钮下的下拉列表中。

Github功能“ Squash and merge”的屏幕截图


GitHub使用与您的帐户关联的默认电子邮件。如果您有多个电子邮件地址,并且需要使用辅助电子邮件地址,则不能使用GH UI。
卡·吉迪

4

假设您在功能/任务1中进行了多次提交。

  1. 转到您的项目分支(project / my_project)

    git checkout project/my_project
    
  2. 创建一个新分支(功能/ task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. 可以--squash选择

    git merge --squash feature/task1
    
  4. 创建一个提交

    git commit -am "add single comments"
    
  5. 推你的分支

    git push --set-upstream origin feature/task1_bugfix
    

1

对于Git

创建一个新功能

通过终端/外壳:

git checkout origin/feature/<featurename>
git merge --squash origin/feature/<featurename>

这不会提交,允许您首先对其进行检查。

然后提交并完成此新分支的功能,并删除/忽略旧分支(您进行开发的分支)。


@Melebius在您的句子中唯一引用“ SourceTree”的内容,如果它是标记或先前的问题:它不再存在。
乔丹·斯特凡内利

1
@JordanStefanelli SourceTree用于此答案原始版本。感谢您通知它已修复!
Melebius

1

如果出现错误:由于未合并文件,因此无法提交。

git checkout master
git merge --squash bugfix
git add .
git commit -m "Message"

修复了所有冲突文件

git add . 

你也可以使用

git add [filename]

0

在压入之前压扁您的本地分支:

  1. 检出相关分支以进行处理(如果尚未检出)。

  2. 找到您想保留的最古老提交的阴影。

  3. 从该提交创建/签出一个新的分支(tmp1)。

    git checkout -b tmp1 <sha1-of-commit>

  4. 合并原来的分支到新的壁球。

    git merge --squash <original branch>

  5. 使用摘要提交消息提交由合并创建的更改。

    git commit -m <msg>

  6. 签出您要压扁的原始分支。

    git checkout <branch>

  7. 重置为您希望保留的原始提交sha。

    git reset --soft <sha1>

  8. 根据新的tmp1分支对该分支重新设置基础。

    git rebase tmp1

  9. 就是这样-现在,一旦确定一切正常,请删除临时tmp1分支。


0

您可以使用我创建的工具来简化此过程:git-squash。例如,要压缩已从master分支分支的feature分支上的所有提交,请编写:

git squash master
git push --force
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.