代码之家  ›  专栏  ›  技术社区  ›  Nik Reiman

如何挤压两个非连续提交?

  •  138
  • Nik Reiman  · 技术社区  · 15 年前

    我对Git中的整个重新定位功能有点陌生。假设我做出了以下承诺:

    A -> B -> C -> D
    

    后来,我意识到 D 包含一个修复程序,该修复程序依赖于添加的一些新代码 A 以及这些承诺属于一起。我如何挤压 和; D 一起离开 B 和; C 独自一人?

    5 回复  |  直到 6 年前
        1
  •  181
  •   Rudi    8 年前

    你可以跑 git rebase --interactive 在B之前重新排序D,然后挤压成A。

    Git将打开一个编辑器,您会看到这样的文件:

    pick aaaaaaa Commit A
    pick bbbbbbb Commit B
    pick ccccccc Commit C
    pick ddddddd Commit D
    
    # Rebase aaaaaaa..ddddddd onto 1234567 (4 command(s))
    #
    # 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
    # x, exec = run command (the rest of the line) using shell
    #
    # These lines can be re-ordered; they are executed from top to bottom.
    #
    # If you remove a line here THAT COMMIT WILL BE LOST.
    #
    # However, if you remove everything, the rebase will be aborted.
    #
    # Note that empty commits are commented out
    

    现在,您更改文件的外观如下:

    pick aaaaaaa Commit A
    squash ddddddd Commit D
    pick bbbbbbb Commit B
    pick ccccccc Commit C
    

    现在Git将A和D的更改合并为一个提交,然后将B和C放在一起。当您不想保留d的提交消息时,也可以使用“fix”关键字。

        2
  •  41
  •   Community Mohan Dere    8 年前

    注意:你应该 未更改已推送的提交 以任何方式向另一个回购 除非你知道 consequences .

    git log --oneline -4

    D commit_message_for_D
    C commit_message_for_C
    B commit_message_for_B
    A commit_message_for_A
    

    git rebase --interactive

    pick D commit_message_for_D
    pick C commit_message_for_C
    pick B commit_message_for_B
    pick A commit_message_for_A
    

    类型 i (将VIM置于插入模式)

    将列表更改为如下所示(不必删除或包含提交消息)。 不要拼错 squash ! :

    pick C commit_message_for_C
    pick B commit_message_for_B
    pick A commit_message_for_A
    squash D
    

    类型 ESC 然后 ZZ (保存并退出VIM)

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

    类型

    将文本更改为新提交消息的外观。我建议这是对提交中更改的描述 A D :

    new_commit_message_for_A_and_D
    

    类型 ESC 然后 ZZ

    Git日志--单线-4

    E new_commit_message_for_A_and_D
    C commit_message_for_C
    B commit_message_for_B
    

    git show E

    (You should see a diff showing a combination of changes from A and D)
    

    您现在创建了一个新的提交 E . 提交 D 已经不在你的历史中了,但不会消失。在这一点上,你仍然可以在一段时间内通过 git rebase --hard D ( git rebase --hard 将销毁任何本地更改! )

        3
  •  3
  •   Adam Johns    9 年前

    对于那些使用 SourceTree :

    确保您还没有推送提交。

    1. 存储库>交互式钢筋库…
    2. 将d(较新的提交)拖动到a(较旧的提交)正上方。
    3. 确保突出显示commit d
    4. 点击 Squash with previous
        4
  •  1
  •   Oleksiy Guzenko    6 年前

    InteractiveRebase工作得很好,直到您拥有具有20-30提交的大功能分支和/或来自master的两个合并或/和在您提交分支时修复冲突。即使在历史中找到我的承诺并取代 pick 具有 squash 这里不工作。所以我在寻找另一种方法找到了这个 article . 我做了一些更改,以便在单独的分支上执行此操作:

    git checkout master
    git fetch
    git pull
    git merge branch-name
    git reset origin/master
    git branch -D branch-name
    git checkout -b branch-name
    git add --all
    #Do some commit
    git push -f --set-upstream origin branch-name
    

    在此之前,我收到了我的请求,大约30次提交,2-3次合并来自master+修复冲突。在这之后,我有了明确的公关承诺。

    另外,这里是巴什 script 在automode中执行此步骤。

        5
  •  -1
  •   Cotton    15 年前

    $git结账大师

    $Git日志--单行

    D
    C
    B
    A
    

    $git rebase--到头部^

    $Git日志--单行

    D
    A
    
    推荐文章