提交的重新排序

Pet*_*ter 82 git branch

我目前正在分支机构,并希望一些提交合并到其他分支:

    a-b-c-d-e-f-g (branchA)
   /
--o-x-x-x-x-x-x-x-x-x-x (master)
   \
    x-x-x-x-x (branchB)
Run Code Online (Sandbox Code Playgroud)

(字母表示提交,"x"是不相关的提交.)

但是我注意到汇集一些提交是个好主意.我想"连接"将a,d,e和g提交到一个补丁中并将其提交给master.提交b和f应该作为一个提交到branchB.是否有一种良好的"git"方式来实现它?

Cas*_*bel 105

您正在寻找的命令git rebase,特别是-i/--interactive选项.

我将假设你想在分支A上保留commit c,并且你真的意味着你想将其他提交移动到其他分支,而不是合并,因为合并是直截了当的.让我们从操纵分支A开始.

git rebase -i <SHA1 of commit a>^ branchA
Run Code Online (Sandbox Code Playgroud)

^意味着先前的提交,因此该命令表示使用"a"之前的提交作为基础来修改分支A. Git将向您显示此范围内的提交列表.重新排序它们并告诉git压缩适当的:

pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f
Run Code Online (Sandbox Code Playgroud)

现在历史应该是这样的:

    c - [a+d+e+g] - [b+f] (branchA)
   /
--o-x-x-x-x-x-x-x-x-x-x (master)
Run Code Online (Sandbox Code Playgroud)

现在,让我们为branchB抓住新压缩的提交b + f.

git checkout branchB
git cherry-pick branchA  # cherry-pick one commit, the tip of branchA
Run Code Online (Sandbox Code Playgroud)

主人的+ d + e + g也一样:

git checkout master
git cherry-pick branchA^
Run Code Online (Sandbox Code Playgroud)

最后,更新branchA,使其指向c:

git branch -f branchA branchA^^
Run Code Online (Sandbox Code Playgroud)

我们现在应该:

    c (branch A) - [a+d+e+g] - [b+f] (dangling commits)
   /
--o-x-x-x-x-x-x-x-x-x-x-[a+d+e+g] (master)
   \
    x-x-x-x-x-[b+f] (branchB)
Run Code Online (Sandbox Code Playgroud)

请注意,如果您想要在分支之间移动多个提交,则可以再次使用rebase(非交互式):

# create a temporary branch
git branch fromAtoB branchA
# move branchA back two commits
git branch -f branchA branchA~2
# rebase those two commits onto branchB
git rebase --onto branchB branchA fromAtoB
# merge (fast-forward) these into branchB
git checkout branchB
git merge fromAtoB
# clean up
git branch -d fromAtoB
Run Code Online (Sandbox Code Playgroud)

最后,免责声明:很有可能以某种方式重新排序提交,使某些提交不再干净.这可能是因为您选择了一个错误的订单(在提交引入其修补的功能之前放置一个补丁); 在这种情况下,你会想要中止rebase(git rebase --abort).否则,您将必须智能地修复冲突(就像您对合并冲突一样),添加修复程序,然后继续运行git rebase --continue.冲突发生时打印的错误消息也提供了这些说明.

  • 为什么不能在分支 A 上执行 `git reset --hard &lt;sha1 of c&gt;` ,而不是执行`gitbranch -fbranchAbranchA^^`? (2认同)
  • 我一直忽略的是,你实际上可以在“--interactive”模式下重新排序提交,而 git 将完成剩下的工作。 (2认同)

Nel*_*elu 54

git rebase -i HEAD~3
Run Code Online (Sandbox Code Playgroud)

3需要重新排序的提交数量在哪里(source)。

这将打开vi,列出从最旧(顶部)到最新(底部)的提交。
现在重新排列行,保存,然后退出编辑器。

ddp将当前行向下
ddkP移动将当前行向上移动(

  • 如果你想使用其他编辑器而不是 vi,你可以在执行 git rebase 之前使用命令 `git config --global core.editor "/path/to/your/editor"` _(当然全局是可选的)_交互地。 (4认同)
  • 使用“nano”编辑器,您可以使用“Ctrl+K”剪切一行,并使用“Ctrl+U”将其粘贴回去。 (4认同)
  • 顺便说一句,对于那些不知道如何使用 vim 的人来说,你不需要一直按`ddp`或`ddkP`,你可以只按`ddp`来剪断行,然后使用`j`或` k` 分别向下和向上移动 (3认同)
  • 对于 vscode 用户:您可以使用 GitLens 扩展,它提供了一个友好的 UI 来进行变基 https://cmolina.dev/posts/2021/06/configure-git/#use-visual-studio-code-for-squashing (3认同)
  • 好东西......但是那些使用“ed”的人呢? (2认同)

cod*_*ape 22

git rebase --interactive 是你想要的命令。

例子:

目前的状态是这样的:

bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git status
On branch master
nothing to commit, working tree clean
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
a6e3c6a (HEAD -> master) Fourth commit
9a24b81 Third commit
7bdfb68 Second commit
186d1e0 First commit
Run Code Online (Sandbox Code Playgroud)

我想重新排序提交9a24b81(第三次提交)和7bdfb68(第二次提交)。为此,我首先在我们要更改的第一个提交之前找到提交。这是提交186d1e0(第一次提交)。

要执行的命令是git rebase --interactive COMMIT-BEFORE-FIRST-COMMIT-WE-WANT-TO-CHANGE,在这种情况下:

bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git rebase --interactive 186d1e0
Run Code Online (Sandbox Code Playgroud)

这将在默认编辑器中打开一个文件,其中包含以下内容:

pick 7bdfb68 Second commit
pick 9a24b81 Third commit
pick a6e3c6a Fourth commit

# Rebase 186d1e0..a6e3c6a onto 186d1e0 (3 commands)
#
# 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
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
Run Code Online (Sandbox Code Playgroud)

请注意,文件中提交的顺序与用于 git log 的顺序相反。在 git log 中,最近的提交位于顶部。在此文件中,最近的提交位于底部。

正如文件底部的评论所解释的,我可以做很多事情,比如压缩、删除和重新排序提交。为了重新排序提交,我编辑了文件,使其看起来像这样(底部注释未显示):

pick 9a24b81 Third commit
pick 7bdfb68 Second commit
pick a6e3c6a Fourth commit
Run Code Online (Sandbox Code Playgroud)

pick每行开头的命令表示“使用(即包含)此提交”,当我使用 rebase 命令保存临时文件并退出编辑器时,git 将执行命令并更新存储库和工作目录:

$ git rebase --interactive 186d1e0
Successfully rebased and updated refs/heads/master.
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
ba48fc9 (HEAD -> master) Fourth commit
119639c Second commit
9716581 Third commit
186d1e0 First commit
Run Code Online (Sandbox Code Playgroud)

注意重写的提交历史。

链接: