如何压缩提交之间有合并-提交?

我在做一个专题分支。

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

因此,当前提交历史记录如下所示。 从现在到过去:

  1. 提交 M yyy (合并)
  2. 第二项

如何压缩以上3个提交到1之前,我合并我的特性分支主人?

93118 次浏览

您可以从 commit 2的父级开始 rebase -i(即从 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

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

Error: commit 是合并,但没有给出 -m 选项。

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

也许有一个更好的方法(我期待着学习) ,但是经过大量的阅读和尝试之后,我最终做的是创建一个供参考的副本分支,然后将当前的分支恢复为 C1,

重置——硬(C1散列)

然后选择 C2,C3,C4,然后压扁,然后重新定位... 结果是:

M-> C

(只有一个提交被源代码重新定义了基础!)

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

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

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

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

git merge master
git squash master

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

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

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

这将从上次合并到工作分支的主提交创建一个新分支。

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

这个工作目录可以获取并应用到 main 上最后一次提交到 work 和 work 分支末端之间的所有更改。所有的工作,包括解决冲突。

此时,您需要处理在工作分支上添加/删除的文件,因为 patch 不是 git。它不知道 Git 在跟踪什么文件。因此,您需要 git add/git rm,直到所有文件都被清点完毕。然后,您只需将更改作为单个提交提交即可。

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

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

签出来自同一个原始分支的新分支,挑选所有的提交(merge-commit 除外) ,然后推送该分支

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

注意,我们分叉的起点分支是相同的,即 master

对于 IntelliJ 用户来说,精挑细选的过程非常简单。

假设特征分支称为 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

enter image description here

  1. 找当地的公关:
gh pr checkout 1938
  1. 添加 upstream以说明从何处获取更改
git remote add upstream git@github.com:minio/console.git
  1. fetchupstream得到所有新的变化
git fetch upstream
  1. 以一种特殊的方式,看:
git rebase -i upstream/master

你会明白的

pick 18eea859 add csr under tenant details


# Rebase 3bfdbb5e..01964c30 onto 3bfdbb5e (1 command)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
#                    commit's log message, unless -C is used, in which case
#                    keep only this commit's message; -c is same as -C but
#                    opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified); use -c <commit> to reword the commit message
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
  1. 只是不要改变 pick让它,如果你选择 squashreword为这个特殊情况下,它不会工作。所有你真正想要的是重新基础您的变化,并删除合并提交从您的 PR,所以只要保存文件,并得到以下:
$ git rebase -i upstream/master
Successfully rebased and updated refs/heads/add-csr-under-tenant-details.
  1. 现在你可以推它了:
git push -f
  1. 压缩,或者实际上重新设置基础,不再在两者之间进行合并提交:

enter image description here