git 如果我已经开始变基,如何将两个提交合并为一个?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2563632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 08:11:04  来源:igfitidea点击:

How can I merge two commits into one if I already started rebase?

gitgit-merge

提问by michael

I am trying to merge 2 commits into 1, so I followed “squashing commits with rebase” from git ready.

我正在尝试将 2 个提交合并为 1 个,因此我遵循了 git ready 中的“使用 rebase 压缩提交”

I ran

我跑了

git rebase --interactive HEAD~2

In the resulting editor, I change pickto squashand then save-quit, but the rebase fails with the error

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

Cannot 'squash' without a previous commit

没有先前的提交就不能“挤压”

Now that my work tree has reached this state, I’m having trouble recovering.

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

The command git rebase --interactive HEAD~2fails with:

该命令git rebase --interactive HEAD~2失败:

Interactive rebase already started

交互式变基已经开始

and git rebase --continuefails with

git rebase --continue失败

Cannot 'squash' without a previous commit

没有先前的提交就不能“挤压”

回答by Greg Bacon

Summary

概括

The error message

错误信息

Cannot 'squash' without a previous commit

没有先前的提交就不能“挤压”

means you likely attempted to “squash downward.” Git always squashes a newer commit into an older commitor “upward” as viewed on the interactive rebase todo list, that is into a commit on a previous line. Changing the command on your todo list's very first line to squashwill always produce this error as there is nothing for the first commit to squash into.

意味着您可能试图“向下挤压”。Git 总是将较新的提交压缩为旧提交或“向上”,如交互式 rebase 待办事项列表中所见,即压缩到前一行的提交中。将待办事项列表第一行上的命令更改为squash总是会产生此错误,因为第一次提交没有任何内容可以压缩。

The Fix

修复

First get back to where you started with

首先回到你开始的地方

$ git rebase --abort

Say your history is

说你的历史是

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

That is, a was the first commit, then b, and finally c. After committing c we decide to squash b and c together:

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

(Note: Running git logpipes its output into a pager, lessby default on most platforms. To quit the pager and return to your command prompt, press the qkey.)

(注意:在大多数平台上git logless默认情况下运行它的输出到寻呼机。要退出寻呼机并返回到命令提示符,请按q键。)

Running git rebase --interactive HEAD~2gives you an editor with

跑步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.
#

(Notice that this todo list is in the reverse order as compared with the output of git log.)

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

Changing b's pickto squashwill result in the error you saw, but if instead you squash c into b (newer commit into the older or “squashing upward”) by changing the todo list to

将 b 更改picksquash将导致您看到的错误,但是如果您通过将待办事项列表更改为

pick   b76d157 b
squash a931ac7 c

and save-quitting your editor, you'll get another editor whose contents are

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

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

b

# This is the 2nd commit message:

c

When you save and quit, the contents of the edited file become commit message of the new combined commit:

当你保存并退出时,编辑过的文件的内容变成了新的组合提交的提交信息:

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

Note About Rewriting History

关于重写历史记录的说明

Interactive rebase rewrites history. Attempting to push to a remote that contains the old history will fail because it is not a fast-forward.

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

If the branch you rebased is a topic or feature branch in which you are working by yourself, no big deal. Pushing to another repository will require the --forceoption, or alternatively you may be able, depending on the remote repository's permissions, to first delete the old branch and then push the rebased version. Examples of those commands that will potentially destroy work is outside the scope of this answer.

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

Rewriting already-published history on a branch in which you are working with other people without verygood reason such as leaking a password or other sensitive details forces work onto your collaborators and is antisocial and will annoy other developers. The “Recovering From an Upstream Rebase” section in the git rebasedocumentationexplains, with added emphasis.

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

Rebasing (or any other form of rewriting) a branch that others have based work on is a bad idea: anyone downstream of it is forced to manually fix their history. This section explains how to do the fix from the downstream's point of view. The real fix, however, would be to avoid rebasing the upstream in the first place.

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

回答by user3828059

If there are multiple commits, you can use git rebase -ito squash two commits into one.

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

If there are only two commits you want to merge, and they are the "most recent two", the following commands can be used to combine the two commits into one:

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

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

回答by pambda

Rebase: You Ain't Gonna Need It:

Rebase:你不需要它:

A simpler way for most frequent scenario.

最常见场景的一种更简单的方法。

In most cases:

大多数情况下:

Actually if all you want is just simply combine several recent commits into onebut do not need drop, rewordand other rebase work.

实际上,如果您想要的只是简单地将最近的几个提交合并为一个但不需要drop,reword和其他 rebase 工作。

you can simply do:

你可以简单地做:

git reset --soft "HEAD~n"
  • Assuming ~nis number of commits to softly un-commit (i.e. ~1, ~2,...)
  • 假设~n是提交到数轻声未提交(即~1~2...)

Then, use following command to modify the commit message.

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

git commit --amend

which is pretty much the same as a long range of squashand one pick.

这是几乎相同的长范围的squash和一个pick

And it works for n commits but not just two commits as above answer prompted.

它适用于 n 次提交,但不仅仅是如上述答案提示的两次提交。

回答by Haimei

First you should check how many commits you have:

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

git log

There are two status:

有两种状态:

One is that there are onlytwo commits:

一是只有两个提交:

For example:

例如:

commit A
commit B

(In this case, you can't use git rebase to do) you need to do following.

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

$ git reset --soft HEAD^1

$ git commit --amend

Another is that there are more than two commits; you want to merge commit C and D.

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

For example:

例如:

commit A
commit B
commit C
commit D

(under this condition, you can use git rebase)

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

git rebase -i B

And than use "squash" to do. The rest thins is very easy. If you still don't know, please read http://zerodie.github.io/blog/2012/01/19/git-rebase-i/

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

回答by Homan

Assuming you were in your own topic branch. If you want to merge the last 2 commits into one and look like a hero, branch off the commit just before you made the last two commits.

假设您在自己的主题分支中。如果您想将最后 2 个提交合并为一个并看起来像一个英雄,请在您进行最后两个提交之前将提交分支。

git checkout -b temp_branch HEAD^2

Then squash commit the other branch in this new branch:

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

git merge branch_with_two_commits --squash

That will bring in the changes but not commit them. So just commit them and you're done.

这将带来更改但不会提交它们。所以只要提交它们,你就完成了。

git commit -m "my message"

Now you can merge this new topic branch back into your main branch.

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

回答by Leom Burke

you can cancel the rebase with

你可以取消 rebase

git rebase --abort

and when you run the interactive rebase command again the 'squash; commit must be below the pick commit in the list

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

回答by VinceStyling

I often use git reset --mixedto revert a base version before multiple commits which you want to merge, then I make a new commit, that way could let your commit newest, assure your version is HEAD after you push to server.

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

commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

If I want to merge head two commits into one, first I use :

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

git reset --mixed 249cf9392da197573a17c8426c282

"249cf9392da197573a17c8426c282" was third version, also is your base version before you merge, after that, I make a new commit :

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

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

It's all, hope is another way for everybody.

就是这样,希望是每个人的另一种方式。

FYI, from git reset --help:

仅供参考,来自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.

回答by Gnanasekar S

$ git rebase --abort

$ git rebase --abort

Run this code at any time if you want to undo the git rebase

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

$ git rebase -i HEAD~2

$ git rebase -i HEAD~2

To reapply last two commits. The above command will open a code editor

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

  • [ The latest commit will be at the bottom]. Change the last commit to squash(s). Since squash will meld with previous commit.
  • Then press esc key and type :wq to save and close
  • [最新提交将在底部]。将最后一次提交更改为壁球。因为壁球会与之前的提交融合。
  • 然后按esc键并输入:wq保存并关闭

After :wq you will be in active rebase mode

在 :wq 之后,您将处于活动 rebase 模式

Note: You'll get another editor if no warning/error messages, If there is an error or warning another editor will not show, you may abort by runnning $ git rebase --abortif you see an error or warning else just continue by running $ git rebase --continue

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

You will see your 2 commit message. Choose one or write your own commit message, save and quit [:wq]

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

Note 2:You may need to force push your changes to the remote repo if you run rebase command

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

$ git push -f

$ git push -f

$ git push -f origin master

$ git push -f origin master

回答by Martin G

Since I use git cherry-pickfor just about everything, to me it comes natural to do so even here.

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

Given that I have branchXchecked out and there are two commits at the tip of it, of which I want to create one commit combining their content, I do this:

鉴于我已经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

If i want to update branchXas well (and I suppose this is the down side of this method) I also have to:

如果我也想更新branchX(我想这是这种方法的缺点),我还必须:

git checkout branchX
git reset --hard <the_new_commit>

回答by Usman

If your master branch git loglooks something like following:

如果您的主分支git log如下所示:

commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

and you want to merge the top two commits just do following easy steps:

并且您想合并前两个提交只需执行以下简单步骤:

  1. First to be on safe side checkout the second last commit in a separate branch. You can name the branch anything. git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
  2. Now, just cherry-pick your changes from the last commit into this new branch as: git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e. (Resolve conflicts if arise any)
  3. So now, your changes in last commit are there in your second last commit. But you still have to commit, so first add the changes you just cherry-picked and then execute git commit --amend.
  1. 首先要安全地在单独的分支中签出第二个最后一次提交。您可以将分支命名为任何名称。git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
  2. 现在,只樱桃采摘从最后的更改提交到这个新的分支为:git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e。(如有冲突解决)
  3. 所以现在,您在上次提交中的更改出现在您的第二次最后提交中。但是您仍然必须提交,因此首先添加您刚刚挑选的更改,然后执行git commit --amend.

That's it. You may push this merged version in branch "merged-commits" if you like.

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

Also, you can discard the back-to-back two commits in your master branch now. Just update your master branch as:

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

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