推送后如何在git中压缩提交?

Posted

技术标签:

【中文标题】推送后如何在git中压缩提交?【英文标题】:How to squash commits in git after they have been pushed? 【发布时间】:2011-08-05 18:56:56 【问题描述】:

这很好地解释了压缩多个提交:

http://git-scm.com/book/en/Git-Branching-Rebasing

但它不适用于已经推送的提交。如何压缩本地和远程存储库中最近的几次提交?

当我做git rebase -i origin/master~4 master时,将第一个保持为pick,将其他三个设置为squash,然后退出(通过emacs中的c-x c-c),我得到:

$ git rebase -i origin/master~4 master
# Not currently on any branch.
nothing to commit (working directory clean)

Could not apply 2f40e2c... Revert "issue 4427: bpf device permission change option added"
$ git rebase -i origin/master~4 master
Interactive rebase already started

其中 2f40 是 pick 提交。现在 4 个提交都没有出现在 git log 中。我希望我的编辑器会重新启动,以便我可以输入提交消息。我做错了什么?

【问题讨论】:

不是那么全面,但易于阅读:internalpointers.com/post/squash-commits-into-one-git 【参考方案1】:

使用

在本地进行 Squash 提交
git rebase -i origin/master~4 master

然后用

强制推送
git push origin +master

--force+ 之间的区别

来自git push的文档:

请注意,--force 适用于所有推送的 ref,因此使用 将push.default 设置为matching 或多次推送 使用remote.*.push 配置的目标可能会覆盖其他引用 比当前分支(包括严格落后的本地参考 他们的远程对手)。要强制只推送到一个分支,请使用 + 在 refspec 前面推送(例如 git push origin +master 强制 推送到master 分支)。

【讨论】:

你也可以git push --force origin master Daenyth:是的,但我总是更喜欢这种语法,因为它更短。 当然,要意识到如果其他人可能已经从远程存储库中提取了,你可能不想这样做 - 在这种情况下的答案是“你不想。” 另外,我认为 OP 正在完全复制命令git rebase -i origin/master,并且实际上想知道如何将提交重新定位到更远的位置,例如git rebase -i origin/master~20 master. g***+ 仅强制以它为前缀的 refspec。 --force 将强制推送所有 refspec。请查看更新后的答案。【参考方案2】:

在一个分支上,我能够这样做(对于最后 4 次提交)

git checkout my_branch
git reset --soft HEAD~4
git commit
git push --force origin my_branch

【讨论】:

在已经推送的分支上使用软命令执行此操作最终会为我推送大量其他人的提交。 一吨?怎么可能超过4?你能详细说明一下吗? 我不确定,但这与试图压缩已经推送的提交有关。看起来其他人在这里经历过类似的事情 - ***.com/questions/5189560/… 我会接受这个作为预期的答案。接受答案的更清洁。 这是只需 4 个步骤即可获得的最清晰、最被接受的答案【参考方案3】:

很多问题可以通过只创建一个branch 来处理&处理master 来避免:

git checkout -b mybranch

以下适用于已推送的remote 提交和remote 推送的提交/local 仅提交的混合:

# example merging 4 commits

git checkout mybranch
git rebase -i mybranch~4 mybranch

# at the interactive screen
# choose fixup for commit: 2 / 3 / 4

git push -u origin +mybranch

我也有一些 pull request notes 可能会有所帮助。

【讨论】:

【参考方案4】:

git rebase -i master

您将打开编辑器 vm 并发送类似这样的消息

Pick 2994283490 commit msg1
f 7994283490 commit msg2
f 4654283490 commit msg3
f 5694283490 commit msg4
#Some message 
#
#some more

在这里,我已将所有其他提交的选择更改为“f”(代表修复)。

git push -f origin feature/feature-branch-name-xyz

这会将所有提交修复为一个提交,并将删除所有其他提交。 我这样做了,它帮助了我。

【讨论】:

这必须是最佳答案,谢谢。我发现这个答案是一种更好的压缩方式,而不是根据提交次数盲目地进行压缩。尤其是使用 VM 编辑器,您可以一次执行很多操作,例如更改提交、删除提交,当然还有压缩。【参考方案5】:

与接受的答案略有不同,但我在挤压时遇到了很多困难,最终得到了它。

$ git rebase -i HEAD~4
在打开的交互式屏幕上,将 pick 替换为 squash 在您要压缩的所有提交的顶部。 保存并关闭编辑器

使用以下方式推送到遥控器:

$ git push origin branch-name --force

【讨论】:

简洁有效,详解: esc --> :wq 前提是编辑器是vi或vim 正确而准确。力推很重要。推前不要拉。【参考方案6】:

为了在一个分支上压缩两个提交,其中一个已经被推送,以下工作:

git rebase -i HEAD~2
    [ pick     older-commit  ]
    [ squash   newest-commit ]
git push --force

默认情况下,这将包括最新提交的提交消息作为对旧提交的评论。

【讨论】:

【参考方案7】:

1) git rebase -i HEAD~4

详细说明:它适用于当前分支; HEAD~4 表示压缩最近的四个提交;交互模式(-i)

2)此时,编辑器打开了提交列表,以更改第二个和后续提交,将 pick 替换为 squash 然后保存。

输出:成功地重新定位和更新了 refs/heads/branch-name。

3)git push origin refs/heads/branch-name --force

输出:

remote:
remote: To create a merge request for branch-name, visit:
remote: http://xxx/sc/server/merge_requests/new?merge_request%5Bsource_branch%5D=sss
remote:To ip:sc/server.git
 + 84b4b60...5045693 branch-name -> branch-name (forced update)

【讨论】:

【参考方案8】:

当您使用 Gitlab 或 Github 时,您可能会以这种方式遇到麻烦。您使用上述方法之一压缩您的提交。我最喜欢的是:

git rebase -i HEAD~4
or
git rebase -i origin/master

为您的提交选择 squash 或 fixup。此时,您将使用 git status 进行检查。消息可能是:

    On branch ABC-1916-remote
    Your branch and 'origin/ABC-1916' have diverged,
    and have 1 and 7 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)

你可能会想拉它。 不要那样做,否则你会遇到和以前一样的情况。

而是通过以下方式推送到您的原点:

git push origin +ABC-1916-remote:ABC-1916

+ 允许强制推送到一个分支。

【讨论】:

拉动没有什么问题,特别是如果你有冲突,它们比你强制推更容易解决 @Ray_Poly - 那不是将那些远程提交作为本地提交放回原处吗?这就是我发现的。 是的,它会创建一个新的提交,但是你可以在那个提交中看到差异,比每次 rebase 都重写 git 历史记录要好【参考方案9】:

Sqush 远程更改

首先确保您的本地主机与远程主机相同 然后将本地功能分支重置为与 master 相同:git 重置 --soft master 然后添加您的所有修改和更改(您在 您刚刚重置为 master 的本地功能分支)到暂存区域:git 添加。 然后提交这些更改: git commit -m "this is the final commit 消息” 然后强制推送到远程分支:git push RemoteBranch --force

【讨论】:

【参考方案10】:

在我的情况下,要求是将所有功能分支提交压缩为一个,以获得干净的提交历史记录。使用 GitHub UI 来执行此操作。

问题:

功能分支(例如:featureBranch)已从 master 创建(一个月前)。 提交了我对 featureBranch 的所有更改(大约 12 次提交,一个月的工作)。并且定期被推送到远程。

要求:

使用 master 更新特性分支并在特性分支中进行一次提交

后续步骤:

在 GitHub UI 中从 master 创建一个新分支(例如:featureBranchLatest)。 创建一个从 featureBranch 到 featureBranchLatest 的 PR。 解决冲突(如果有)。将 PR 与 GitHub UI 中的 squash 提交选项合并。 (更改提交消息以获得更清晰的消息)。

现在 featureBranchLatest 将在单个提交中包含所有所需更改的单个提交,以及来自 master 的最新更改。如果不需要参考,请删除旧分支 featureBranch。

【讨论】:

以上是关于推送后如何在git中压缩提交?的主要内容,如果未能解决你的问题,请参考以下文章

如何在拉取请求中压缩提交

在原始仓库接受拉取请求后,有没有办法在 fork 中压缩提交?

如何在 iOS 的文件管理器中压缩空文件夹?

如何在 C# 中压缩(和解压缩)字节 []?

Windows7中压缩卷后变为黑色的未分配空间如何变为绿色的可用空间

如何在 Android 中压缩字符串