如果我已经开始使用rebase,如何将两个提交合并为一个?

mic*_*ael 1111 git git-merge

我试图将2个提交合并为1,所以我从git准备好跟随"压缩提交与rebase".

我跑了

git rebase --interactive HEAD~2
Run Code Online (Sandbox Code Playgroud)

在生成的编辑器中,我更改picksquash然后保存退出,但是rebase因错误而失败

没有先前的提交,不能'挤压'

既然我的工作树已达到这种状态,我就无法恢复了.命令git rebase --interactive HEAD~2失败

交互式rebase已经开始

git rebase --continue失败了

没有先前的提交,不能'挤压'

Gre*_*con 1685

摘要

错误消息

没有先前的提交,不能'挤压'

意味着你可能试图"向下压缩." Git总是把一个较新的提交压缩到一个较旧的提交或者在交互式rebase待办事项列表中查看的"向上",即在前一行的提交中.更改todo列表的第一行上的命令squash将始终产生此错误,因为第一次提交压缩没有任何内容.

修复

首先回到你开始的地方

$ git rebase --abort
Run Code Online (Sandbox Code Playgroud)

说你的历史是

$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a
Run Code Online (Sandbox Code Playgroud)

也就是说,a是第一次提交,然后是b,最后是c.在提交c之后,我们决定将b和c压缩在一起:

(注意:在大多数平台上默认情况下,将git log其输出管道输出到寻呼机less.要退出寻呼机并返回到命令提示符,请q按键.)

Running git rebase --interactive HEAD~2给你一个编辑器

pick b76d157 b
pick a931ac7 c

# Rebase df23917..a931ac7 onto df23917
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Run Code Online (Sandbox Code Playgroud)

(请注意,与输出相比,此待办事项列表的顺序相反git log.)

将b更改picksquash将导致您看到的错误,但是如果您改变todo列表,则将c压缩为b(较新的提交到较旧的或"向上挤压")

pick   b76d157 b
squash a931ac7 c
Run Code Online (Sandbox Code Playgroud)

并保存退出您的编辑器,您将获得其内容的另一个编辑器

# This is a combination of 2 commits.
# The first commit's message is:

b

# This is the 2nd commit message:

c
Run Code Online (Sandbox Code Playgroud)

保存并退出时,已编辑文件的内容将成为新组合提交的提交消息:

$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a
Run Code Online (Sandbox Code Playgroud)

关于重写历史的注意事项

交互式rebase重写历史记录.尝试推送到包含旧历史记录的遥控器将失败,因为它不是快进的.

如果您重新分支的分支是您自己工作的主题或功能分支,那么没什么大不了的.推送到另一个存储库将需要该--force选项,或者您可以根据远程存储库的权限,首先删除旧分支,然后推送已更新的版本.可能会破坏工作的那些命令的示例超出了本答案的范围.

重写的一个分支在你与其他人一起工作,而不已经发布的历史非常充分的理由,如泄露密码或其他敏感信息的工作力量到你的合作者,是反社会的,并会惹恼其他开发商.文档中"从上游Rebase中恢复"部分进行了git rebase解释,并进一步强调了这一点.

重新定位(或任何其他形式的重写)其他人基于其工作的分支是一个坏主意:它下游的任何人都被迫手动修复其历史记录.本节介绍如何从下游的角度进行修复.然而,真正的解决方法是首先避免重新定位上游....

  • @Mithril `git rebase --interactive HEAD~3`,然后将 c 行移动到 a 行下方。将 c 行的 `pick` 更改为 `s`,然后退出编辑器。 (2认同)

小智 395

如果有多个提交,您可以使用git rebase -i将两个提交压缩为一个.

如果您只想合并两个提交,并且它们是"最近的两个",则可以使用以下命令将两个提交合并为一个:

git reset --soft "HEAD^"
git commit --amend
Run Code Online (Sandbox Code Playgroud)

  • @ dr0i你可以根据需要合并任意数量的提交,只要它们是**最后的X提交,**而不是中间的某个地方.只需运行`git reset --soft HEAD~10`,其中10是您要合并的提交数. (48认同)
  • 你不能以任意顺序加入 - 只有**最后两次提交**. (17认同)
  • 你也可以重置为一个特定的提交,如果你不想通过使用`git reset --soft 47b5c5 ...来计算`HEAD`的数量,其中`47b5c5 ...`是的SHA1 ID承诺. (8认同)
  • 与rebase相比有什么缺点?我发现一个更简单易用. (6认同)
  • 如果您没有远程原点设置,并且只有两次提交,则可以使用此选项. (2认同)
  • 请添加"git push -f origin master"可能是必要的. (2认同)

pam*_*bda 101

Rebase:你不需要它:

对于最常见的情况,更简单的方法.

在多数情况下:

实际上,如果你想要的只是将几个最近的提交合并为一个 但不需要drop,reword以及其他的rebase工作.

你可以简单地做:

git reset --soft "HEAD~n"
Run Code Online (Sandbox Code Playgroud)
  • 假设~n是提交的数字轻声未提交(即~1,~2...)

然后,使用以下命令修改提交消息.

git commit --amend
Run Code Online (Sandbox Code Playgroud)

这与长距离squash和长距离非常相似pick.

并且它适用于n次提交但不仅仅是两次提交,如上面的答案提示.

  • 如果您想要除了压缩提交之外还要进行一些额外的清理,例如在中间删除1个提交或更改一行代码,这是很好的. (3认同)
  • 所以要将`n`最近的提交加入到一个,首先使用`git reset --soft @~m`,其中`m = n - 1` (3认同)
  • 假设“~n”是软取消提交的提交次数(即“~1”、“~2”,...) (2认同)

Hai*_*mei 52

首先,您应该检查您拥有的提交数量:

git log
Run Code Online (Sandbox Code Playgroud)

有两种状态:

一个是只有两个提交:

例如:

commit A
commit B
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,您不能使用git rebase)您需要执行以下操作.

$ git reset --soft HEAD^1

$ git commit --amend
Run Code Online (Sandbox Code Playgroud)

另一个是有两个以上的提交; 你想合并提交C和D.

例如:

commit A
commit B
commit C
commit D
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,你可以使用git rebase)

git rebase -i B
Run Code Online (Sandbox Code Playgroud)

而不是用"壁球"来做.剩下的很容易.如果您还不知道,请阅读http://zerodie.github.io/blog/2012/01/19/git-rebase-i/

  • 合并存储库中的第一个也是唯一的两个提交,正是我的边缘情况:-) (2认同)

Hom*_*man 28

假设你在自己的主题分支.如果要将最后两个提交合并为一个并且看起来像英雄,请在最后两次提交之前分支提交.

git checkout -b temp_branch HEAD^2
Run Code Online (Sandbox Code Playgroud)

然后squash在这个新分支中提交另一个分支:

git merge branch_with_two_commits --squash
Run Code Online (Sandbox Code Playgroud)

这将带来变化,但不会提交它们.所以只需提交它们就可以了.

git commit -m "my message"
Run Code Online (Sandbox Code Playgroud)

现在,您可以将此新主题分支合并回主分支.

  • 这对我来说实际上是最有用的答案,因为它不需要手动变基,而只是将整个分支的所有提交压缩成一个提交.非常好. (4认同)
  • 最近版本的 git 有什么变化吗?当我在 git 2.17 版中尝试第一个命令 (`git checkout -b combine-last-two-commits "HEAD^2"`) 时,出现错误:`fatal: 'HEAD^2' is not a commit and a无法从中创建分支“combine-last-two-commits” (2认同)

Leo*_*rke 22

你可以用.取消rebase

git rebase --abort
Run Code Online (Sandbox Code Playgroud)

当你再次运行交互式rebase命令时,'squash; commit必须低于列表中的pick commit


Vin*_*ing 16

我经常使用git reset --mixed在你想要合并的多次提交之前恢复基本版本,然后我进行新的提交,这样可以让你的提交最新,确保你的版本在推送到服务器之后是HEAD.

commit ac72a4308ba70cc42aace47509a5e
Author: <me@me.com>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <me@me.com>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <ralph@me.com>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation
Run Code Online (Sandbox Code Playgroud)

如果我想将两个提交合并为一个,首先我使用:

git reset --mixed 249cf9392da197573a17c8426c282
Run Code Online (Sandbox Code Playgroud)

"249cf9392da197573a17c8426c282"是第三个版本,在你合并之前也是你的基础版本,之后,我做了一个新的提交:

git add .
git commit -m 'some commit message'
Run Code Online (Sandbox Code Playgroud)

总而言之,希望是每个人的另一种方式.

仅供参考,来自git reset --help:

 --mixed
     Resets the index but not the working tree (i.e., the changed files are
     preserved but not marked for commit) and reports what has not been
     updated. This is the default action.
Run Code Online (Sandbox Code Playgroud)


Gna*_*r S 12

$ git rebase --abort

如果要撤消git rebase,请随时运行此代码

$ git rebase -i HEAD~2

重新申请最后两次提交.上面的命令将打开代码编辑器

  • [ 最新提交将在底部 ].将最后一次提交更改为squash(s).由于壁球将与先前的提交融合.
  • 然后按esc键并键入:wq以保存并关闭

之后:wq你将处于活跃的rebase模式

注意:如果没有警告/错误消息,您将获得另一个编辑器.如果出现错误或警告其他编辑器将不显示,$ git rebase --abort如果您看到错误或警告,您可以通过runnning中止, 否则只需继续运行$ git rebase --continue

您将看到2提交消息.选择一个或编写自己的提交消息,保存并退出[:wq]

注意2:如果运行rebase命令,则可能需要强制将更改推送到远程仓库

$ git push -f

$ git push -f origin master


Ali*_*ili 7

如果您想将多个提交压缩在一起,则可以使用交互式变基方法来实现。(感谢 Mads 教我这一点!)

  • git rebase origin/develop -i
  • 然后,您只需在要压缩的提交前面写一个 's' 并将它们汇总到主提交中

处于 git rebase 交互模式 (vim) 时的专业提示:

  1. 导航到您要修改的提交行
  2. (ESC) ciw- (更改内部单词)将更改光标下的整个单词。
  3. 输入您想要执行的操作,例如s挤压
  4. (ESC)wq写得相当,你就完成了。

在此输入图像描述

然后git push -f