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


549

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

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

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

编辑:当我这样做时git rebase -i origin/master~4 master,将第一个保留为pick,将其他三个保留为squash,然后退出(通过emacs中的cx cc),我得到:

$ 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。我希望编辑器可以重新启动,以便我可以输入提交消息。我究竟做错了什么?

Answers:


779

壁球在本地提交

git rebase -i origin/master~4 master

然后用力推

git push origin +master

--force和之间的区别+

从以下文档中git push

请注意,这--force适用于所有推送的ref,因此在push.default设置为matching或配置了多个推送目标的情况下使用它remote.*.push可能会覆盖当前分支以外的其他ref(包括严格位于其远程副本后面的本地ref)。要仅将一个推送强制到一个分支,请+ 在refspec前面使用a 进行推送(例如git push origin +master,强制推送到该master分支)。


30
您还可以git push --force origin master
Daenyth 2011年

7
Daenyth:是的,但是我总是喜欢这种语法,因为它较短。
Alan Haggai Alavi

85
当然,要意识到,如果其他人可能已经从远程存储库中拉出了,则您可能不想这样做-在这种情况下,答案是“您不这样做”。
卡斯卡贝尔2011年

10
另外,我认为OP确实是在复制命令git rebase -i origin/master,并且实际上想知道如何比更远的时间重新构建提交,例如git rebase -i origin/master~20 master
卡斯卡贝尔2011年

6
gstackoverflow+仅强制以其为前缀的 refspec--force将强制所有refspec被推送。请查看更新后的答案。
艾伦·哈盖·阿拉维

119

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

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

1
在已经推送的分支上使用软命令执行此操作最终导致为我推送了其他许多人的提交。
cchamberlain

3
一吨?怎么可能超过4?你能详细说明吗?
jakob-r

我不确定,但这与尝试压缩已经推送的提交有关。与其他人一样的外观经历过类似的在这里- stackoverflow.com/questions/5189560/...
cchamberlain

4
我会接受这个作为预期的答案。更干净的接受答案。
vikramvi

4
这是仅用4个步骤即可得到的最清晰,最可接受的答案
Ameya Salagre 18-10-10

45

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

$ git rebase -i HEAD~4
  • 在打开的交互式屏幕上,替换选择南瓜 顶部为所有要壁球提交。
  • 通过保存并关闭编辑器 esc --> :wq

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

$ git push origin branch-name --force

2
简短,有效,详尽:
terwxqian

22

只需创建一个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

我也有一些请求请求注释,这可能会有所帮助。


17

git rebase -i master

您将打开编辑器vm,并使用msgs这样的操作

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

这会将所有提交固定为一个提交,并删除所有其他提交。我做到了,这对我有帮助。


3

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

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

为您的提交选择壁球或修正。此时,您将使用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

2

要压缩两个提交(其中一个已经被推送)在单个分支上,可以进行以下工作:

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

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


2

1) git rebase -i HEAD~4

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

2)这时,编辑器打开,并带有提交列表,以更改第二个及以后的提交,用南瓜替换pick然后保存。

输出:成功地重新建立了基准并更新了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)
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.