提交的重新排序


104

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

    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)

(字母表示提交,而“ x”是不相关的提交。)

但是我注意到合并一些提交是个好主意。我想将a,d,e和g“串联”提交到一个补丁中,并将其提交给master。提交b和f应该作为对branchB的一次提交。是否有一种好的“ git”式方法来实现?


4
已经给出的两个答案都提到了正确的命令,但是我认为,与该任务一样基本的任务,值得在StackOverflow上获得真正的说明,因此我已经发布了一些。(我很惊讶,以前找不到很好的问题可以链接。)
Cascabel,2010年

Answers:


125

您要查找的命令是git rebase,特别是该-i/--interactive选项。

我假设您想将提交c保留在分支A上,并且您确实的确想将其他提交移至其他分支,而不是合并,因为合并很简单。让我们开始处理分支A。

git rebase -i <SHA1 of commit a>^ branchA

^先前的提交装置,所以这个命令说使用所述提交的“a”为基准之前变基支路A。Git将向您显示此范围内的提交列表。重新排列它们,并告诉git压缩适当的:

pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f

现在,历史记录应如下所示:

    c - [a+d+e+g] - [b+f] (branchA)
   /
--o-x-x-x-x-x-x-x-x-x-x (master)

现在,让我们来获取分支B的新压缩的b + f提交。

git checkout branchB
git cherry-pick branchA  # cherry-pick one commit, the tip of branchA

对于master的a + d + e + g也是如此:

git checkout master
git cherry-pick branchA^

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

git branch -f branchA branchA^^

现在,我们应该有:

    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)

请注意,如果您有多个提交要在分支之间移动,则可以再次使用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

最后,免责声明:很有可能对提交进行重新排序,以使某些不再干净地应用。这可能是因为您选择了错误的顺序(在提交之前引入了补丁以介绍其补丁的功能);在这种情况下,您将需要中止rebase(git rebase --abort)。否则,您将必须智能地解决冲突(就像处理合并冲突一样),添加修复程序,然后git rebase --continue继续进行下去。冲突发生时打印的错误消息也提供了这些说明。


图表git branch -f branchA branchA^^错了吗?即,不应该被branchA指向c。在这一点上,使得该图的第一行是c (branchA)c - [a+d+e+g] - [b+f] (branchA)
ntc2 2012年

@enoksrd:是的,有一个错误,但是您的编辑中有错误。如果有机会在这里,我会修复的。
卡斯卡贝尔2012年

git branch -f branchA branchA^^为什么不做git reset --hard <sha1 of c>分支A 而不是为什么呢?
米哈伊尔·瓦西里耶夫

17
git rebase -i HEAD~3

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

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

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


9

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

我想重新排序提交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

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

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

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

正如文件底部的注释说明的那样,我可以执行多种操作,例如压缩,删除和重新排列提交。为了重新排序提交,我编辑了文件,使其看起来像这样(底部注释未显示):

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

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

注意重写的提交历史记录。

链接:


1
请从您的链接中添加相关详细信息,以提供完整且完整的答案。所以皱着眉头“仅链接的答案”。具体来说,一个人将如何git rebase --interactive用于实现OP的目标?
SherylHohman

第二个链接现在不存在。
devsaw

添加了内容,使答案完整且独立。删除了第二个链接。
codeape19年


-1

git rebase是您想要的。签出--interactive选项。


4
请从您的链接中添加相关详细信息,以提供完整且完整的答案。所以皱着眉头“仅链接的答案”。
SherylHohman
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.