96

我正在开发一个功能分支。

  1. 做了几次提交。压扁的提交。
  2. 将更改推送到远程分支。有冲突。
  3. 合并来自 master 的更改,解决了功能分支上的冲突。
    • git fetch origin master
    • git merge FETCH_HEAD
    • 手动解决冲突。
    • git commit
    • git push
  4. 我又做了一个承诺。

所以,当前的提交历史看起来像这样。从现在到旧:

  1. 提交 3
  2. 提交 M yyy(合并)
  3. 提交 2

在将功能分支合并到 master 之前,如何将 3 个以上的提交压缩为 1 个?

4

6 回答 6

51

您可以rebase -icommit 2' 的父级开始(即,master您从中分支的提交。当您到达合并提交时,您可能必须重新解决冲突。

所以如果你的历史看起来像

  * D commit 3 (HEAD)
  * M merge
 /|
| * C commit 2
* | B commit on master
|/
* A (master)

开始git rebase -i A。您将看到一个提交列表,包括masteryour_branch,但不包括合并提交。pick第一个(BC,取决于时间)和squash其余的。

于 2015-05-09T18:28:32.700 回答
13

您可以使用我专门为此任务创建的工具:

https://github.com/sheerun/git-squash

只需要合并master分支,然后运行squashing命令:

git merge master
git squash master
于 2020-06-01T19:40:37.867 回答
10

假设功能分支被调用feature并且主分支main

从以下位置创建一个临时分支main

git checkout -b temp main

feature分支压扁:

git merge --squash feature

提交更改(提交消息包含所有压缩的提交消息):

git commit

返回feature分支并将其指向temp分支:

git checkout feature
git reset --hard temp

删除临时分支:

git branch -d temp
于 2021-11-03T15:26:43.700 回答
5

我发现不必重新解决冲突的唯一方法是:

给定分支主要和分支工作,执行以下步骤:

git checkout -b work-squashed `git merge-base main work`

这会从您合并到工作分支的最后一个主提交创建一个新分支。

git diff work-squashed...work | patch -p1

这将抓取并应用到工作目录中在最后一次提交上合并到工作和工作分支尖端之间的所有更改。换句话说,所有的工作,包括已解决的冲突。

此时您需要处理在工作分支上添加/删除的文件,因为补丁不是 git。它不知道 git 正在跟踪哪些文件。因此,您需要 git add/git rm 直到所有文件都被计算在内。然后,您只需将更改作为单个提交提交。

于 2021-04-11T05:50:41.020 回答
3

就我而言,我开始使用一个有多个提交的分支,然后与主/源分支合并,然后是更多提交,我想压缩所有提交,但由于合并提交而不断遇到错误:

错误:提交是一个合并,但没有给出 -m 选项。

->C1->C2->M(与源分支合并)->C3->C4

可能有更好的方法(我期待学习),但经过大量阅读和反复试验后,我最终做的是创建一个复制分支以供参考,然后将当前分支恢复为 C1,

重置 --hard (C1 哈希)

然后挑选C2,C3,C4,然后挤压,然后重新定位......导致:

M->C

(只有一个已用源重新定位的提交!)

我希望这可以帮助其他有同样问题的人。

于 2019-09-05T00:49:16.597 回答
1

当我使用 Github UI 提交代码更改,然后在本地提交更改(不更新本地克隆),然后尝试将本地提交推送到源时,我遇到了这个问题。结果创建了合并提交。

master
       \ 
         remote-branch --- commit #1 ---------------MergeCommit
                                                    ^
             |                                      |    
           local-branch -------------- commit #2 --- 

从同一个 origin 分支签出一个新分支,cherry-pick除merge-commit 之外的所有提交,然后推送该分支

master
       \ 
         new-branch --------------------------------------- Squash-commits
                                   ^                     ^
             |                     |   < Cherry-pick >   |                      
         previous-branch -----commit #1 --------- commit #2 

请注意,我们从中分叉的 origin-branch 是相同的,即master

对于 IntelliJ 用户来说,挑选樱桃的过程很简单。因此,新分支不会有合并提交。

于 2021-10-01T10:07:54.710 回答