我试图合并2个提交为1,所以我遵循“压缩提交与rebase”从git就绪。

我跑

git rebase --interactive HEAD~2

在结果编辑器中,我将pick更改为squash,然后save-quit,但由于出现错误,重基操作失败

没有之前的提交就不能“squash”

现在我的工作树已经达到了这个状态,我很难恢复。

命令git rebase——interactive HEAD~2失败:

交互式改基已经开始

git rebase -continue失败

没有之前的提交就不能“squash”


你可以用

git rebase --abort

当你再次运行交互式rebase命令时,'squash;Commit必须在列表中选择Commit的下面


总结

错误消息

没有之前的提交就不能“squash”

意味着你可能试图“向下挤压”。Git总是将一个新的提交压缩到一个旧的提交中,或者在交互的rebase todo列表中看到的“向上”,即压缩到前一行的提交中。将待办事项列表的第一行命令更改为“压缩”总是会产生这个错误,因为没有任何东西可以让第一个提交进行压缩。

修复

先回到你开始的地方

$ git rebase --abort

说你的历史

$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a

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

(注意:运行git日志将其输出输送到分页器,在大多数平台上默认情况较少。要退出寻呼机并返回命令提示符,请按q键。)

运行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.
#

(请注意,此todo列表与git log的输出顺序相反。)

将b的选择更改为squash将导致您看到的错误,但如果相反,通过将todo列表更改为将c压缩到b(新的提交到旧的或“向上压缩”)

pick   b76d157 b
squash a931ac7 c

保存退出编辑器,你会得到另一个编辑器,它的内容是

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

b

# This is the 2nd commit message:

c

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

$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a

关于重写历史的说明

交互式rebase重写历史。试图推到包含旧历史记录的远程将失败,因为它不是快进。

如果你重基的分支是你自己工作的主题或特性分支,没有什么大不了的。推送到另一个存储库将需要——force选项,或者根据远程存储库的权限,您可以先删除旧的分支,然后再推送重新构建的版本。那些可能破坏工作的命令的示例超出了这个回答的范围。

在你和其他人一起工作的分支上重写已经发布的历史,而没有很好的理由,比如泄露密码或其他敏感细节,会迫使你的合作者承担工作,这是反社会的,会惹恼其他开发人员。git Rebase文档中的“从上游Rebase中恢复”部分解释了这一点,并增加了重点。

重基于(或任何其他形式的重写)其他人基于工作的分支是一个坏主意:下游的任何人都被迫手动修复他们的历史。本节将从下游的角度解释如何进行修复。然而,真正的解决办法是首先避免上游的基地改变。...


如果你的主分支git日志看起来像下面这样:

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

你想合并前两个提交,只需执行以下简单的步骤:

首先,为了安全起见,在一个单独的分支签出第二个最后提交。你可以给分支起任何名字。Git checkout 77df2a40e53136c7a2d58fd847372 -b合并提交 现在,只需要从上次提交到这个新分支的更改中选择:git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e。(如有冲突,应及时解决) 你在上次提交中的改变在第二次提交中。但是你仍然需要提交,所以首先添加你刚刚选择的更改,然后执行git commit—amend。

就是这样。如果你愿意,你可以在分支“merge -commits”中推送这个合并的版本。

此外,您现在可以在主分支中丢弃连续两次提交。只需将你的主分支更新为:

git checkout master
git reset --hard origin/master (CAUTION: This command will remove any local changes to your master branch)
git pull

我经常使用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

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

git reset --mixed 249cf9392da197573a17c8426c282

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

git add .
git commit -m 'some commit message'

希望对每个人来说都是另一种方式。

供参考,从git重置——帮助:

 --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.

假设你在自己的主题分支里。如果你想把最后两个提交合并成一个,看起来像一个英雄,就在你做最后两个提交之前分支提交(使用相对提交名称HEAD~2指定)。

git checkout -b temp_branch HEAD~2

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

git merge branch_with_two_commits --squash

这将带来改变,但不会导致改变。所以只要承诺就行了。

git commit -m "my message"

现在您可以将这个新的主题分支合并回您的主分支。


首先你应该检查你有多少提交:

git log

有两种状态:

一是只有两次提交:

例如:

commit A
commit B

(在这种情况下,你不能使用git rebase来做)你需要做下面的事情。

$ git reset --soft HEAD^1

$ git commit --amend

另一种情况是提交次数超过两次;你想合并提交C和D。

例如:

commit A
commit B
commit C
commit D

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

git rebase -i B

而不是用“壁球”来做。剩下的就很简单了。如果你还不知道,请阅读http://zerodie.github.io/blog/2012/01/19/git-rebase-i/


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

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

git reset --soft "HEAD^"
git commit --amend

因为我对几乎所有的东西都使用git,所以对我来说,即使在这里这样做也是很自然的。

假设我签出了branchX,在它的顶端有两个提交,其中我想创建一个合并它们内容的提交,我这样做:

git checkout HEAD^ // Checkout the privious commit
git cherry-pick --no-commit branchX // Cherry pick the content of the second commit
git commit --amend // Create a new commit with their combined content

如果我想更新branchX以及(我认为这是这个方法的缺点),我也必须:

git checkout branchX
git reset --hard <the_new_commit>

$git变基--堕胎

如果你想要撤销git rebase,可以在任何时候运行这段代码

我们赢了

重新应用最近两次提交。上面的命令将打开一个代码编辑器

[最近一次提交将在底部]。改变最后一个 致力于壁球运动。因为squash将与之前的提交融合。 然后按esc键并输入:wq保存退出

输入:wq后,您将进入active rebase模式

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

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

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

$ git push -f

$ git push -f origin master


Rebase:你不需要它:

对于最常见的场景,这是一种更简单的方法。

在大多数情况下:

实际上,如果你想要的只是简单地将最近的几次提交合并成一个,而不需要删除,重写和其他rebase工作。

你可以简单地做:

git reset --soft "HEAD~n"

假设~n是软取消提交的提交数(即~1,~2,…)

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

git commit --amend

这和长范围的壁球和单挑是差不多的。

它适用于n次提交,而不是像上面提示的那样只适用于两次提交。


如果您想合并两个最近的提交,而只使用旧的提交的消息,您可以使用expect自动化该过程。

我认为:

您使用vi作为编辑器 每次提交只有一行

我用git版本2.14.3 (Apple git -98)进行了测试。


#!/usr/bin/env expect
spawn git rebase -i HEAD~2

# change the second "pick" to "squash"
# down, delete word, insert 's' (for squash), Escape, save and quit
send "jdwis \033:wq\r"

expect "# This is a"

# skip past first commit message (assumed to be one line), delete rest of file
# down 4, delete remaining lines, save and quit
send "4jdG\r:wq\r"

interact

让我给你一个更简单的方法,

你可以做以下事情,而不是深入到GIT的深层概念中去,并为编辑的螃蟹而烦恼;

假设您从master创建了一个名为bug1的分支。向bug1提交2次。使用这些更改只修改了2个文件。

将这两个文件复制到文本编辑器中。结账的主人。粘贴文件。提交。

那么简单。


添加到@greg的答案后,你完成了所有的事情,即压缩提交,如果你做git push(原始提交将保留在分支),而如果你做git push -f origin提交将被删除。 例如,你合并了提交B和提交C,如果你使用git push,你将有提交B,提交C和提交BC,但如果你使用git push -f origin,你将只有提交BC


如果你想把几个提交压缩在一起,你可以使用交互式的rebase方法。(谢谢小麦教我这些!)

Git rebase origin/develop -i 然后你只需在你想要压缩的提交前写一个's',让它们卷到主提交中

在git rebase交互模式(vim)下的提示:

导航到要修改的提交行 (ESC) ciw -(改变内部单词)将改变光标下的整个单词。 输入你想做的,例如s表示压扁 (ESC) wq写得挺,你就搞定了。

然后git push -f