首页 文章

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

提问于
浏览
1057

我试图将2个提交合并为1,所以我跟着“squashing commits with rebase” from git ready .

我跑了

git rebase --interactive HEAD~2

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

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

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

交互式rebase已经开始

git rebase --continue 失败了

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

11 回答

  • 14

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

    git checkout -b temp_branch HEAD^2
    

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

    git merge branch_with_two_commits --squash
    

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

    git commit -m "my message"
    

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

  • 52

    你可以用 . 取消rebase

    git rebase --abort
    

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

  • 1

    摘要

    错误消息

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

    意味着你可能试图“向下挤压 . ” Git always squashes a newer commit into an older commit 或在交互式rebase待办事项列表中查看的“向上”,即在前一行的提交中 . 将todo列表的第一行上的命令更改为 squash 将始终产生此错误,因为第一次提交没有任何内容可以压缩 .

    修复

    首先回到你开始的地方

    $ git rebase --abort
    

    说你的历史是

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

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

    (注意:在大多数平台上,默认情况下运行 git log 将其输出管道传输到寻呼机,less . 要退出寻呼机并返回到命令提示符,请按 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.
    #
    

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

    将b的 pick 更改为 squash 将导致您看到的错误,但如果您改为将待办事项列表更改为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 选项,或者您可以根据远程存储库的权限首先删除旧分支,然后推送已更新的版本 . 可能会破坏工作的那些命令的示例超出了本答案的范围 .

    在没有很好理由的情况下重写已经发布的历史记录,例如泄露密码或其他敏感细节会导致您的协作者工作并反社会,并会惹恼其他开发人员 . “Recovering From an Upstream Rebase” section in the git rebase documentation解释说,更加强调 .

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

  • 1626

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

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

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

    Rebase:你不需要它:

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

    在大多数情况下:

    实际上,如果你想要的只是 simply combine several recent commits into one 但不需要 dropreword 和其他rebase工作 .

    你可以简单地做:

    git reset --soft "HEAD~n"
    
    • 假设 ~n 是轻微取消提交的提交数(即 ~1~2 ,...)

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

    git commit --amend
    

    这与 squash 的长距离和一个 pick 几乎相同 .

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

  • 1

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

    git log
    

    有两种状态:

    一个是 only 两个提交:

    例如:

    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
    

    并且比使用"squash"做 . 其余的变薄了很容易如果您还不知道,请阅读http://zerodie.github.io/blog/2012/01/19/git-rebase-i/

  • 22

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

    $ git rebase --abort

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

    $ git rebase -i HEAD~2

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

    • [ The latest commit will be at the bottom ] . 将最后一次提交更改为squash(s) . 由于壁球将与先前的提交融合 .

    • 然后按esc键并键入:wq以保存并关闭

    After :wq you will be in active rebase mode

    Note :如果没有警告/错误消息,你会得到另一个编辑器,如果有错误或警告其他编辑器不显示,你可以通过运行 $ git rebase --abort 中止,如果你看到错误或警告其他只是继续运行 $ git rebase --continue

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

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

    $ git push -f

    $ git push -f origin master

  • 2

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

    鉴于我已经签出了 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>
    
  • 77

    如果你的主分支 git log 看起来如下:

    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 merged-commits

    • 现在,只需从最后一次提交中选择您的更改为: git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e . (如果出现任何冲突,解决冲突)

    • 现在,您在上一次提交中的更改将在您的第二次提交中出现 . 但是你仍然必须提交,所以首先添加你刚刚挑选的更改,然后执行 git commit --amend .

    而已 . 如果您愿意,可以将此合并版本推送到分支“merged-commits”中 .

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

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

    如果要组合两个最新的提交并只使用较旧的提交消息,则可以使用expect自动执行该过程 .

    我假设:

    • 您正在使用vi作为编辑器

    • 您的提交各自为一行

    我测试了 git version 2.14.3 (Apple Git-98) .


    #!/usr/bin/env expect
    spawn git rebase -i HEAD~2
    
    # down, delete word, insert 's' (for squash), Escape, save and quit
    send "jdwis \033:wq\r"
    
    expect "# This is a"
    
    # down 4, delete 3 lines, save and quit
    send "4j3d\r:wq\r"
    
    interact
    

相关问题