git 重新排序提交

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2740537/
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:19:54  来源:igfitidea点击:

Reordering of commits

gitbranch

提问by Peter

I'm currently working on a branch and want some commits to merge into other branches:

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

    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)

(Letters denote commits, and the "x" are irrelevant commits.)

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

However I noticed that it would be a good idea to pool some commits. I want to "concatenate" commit a, d, e and g into one patch and commit it to master. Commits b and f should go as one commit to branchB. Is there a good 'git'-ish way to achieve it?

但是我注意到汇集一些提交是个好主意。我想“连接”提交 a、d、e 和 g 到一个补丁中并将其提交给 master。提交 b 和 f 应该作为对 branchB 的一次提交。有没有一个很好的 'git'-ish 方式来实现它?

回答by Cascabel

The command you're looking for is git rebase, specifically the -i/--interactiveoption.

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

I'm going to assume you want to leave commit c on branch A, and that you really do mean you want to move the other commits to the other branches, rather than merging, since merges are straightforward. Let's start by manipulating branch A.

我将假设您希望将提交 c 留在分支 A 上,并且您确实希望将其他提交移动到其他分支,而不是合并,因为合并很简单。让我们从操作分支 A 开始。

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

The ^means the previous commit, so this command says to rebase branch A using the commit before "a" as the base. Git will present you with a list of the commits in this range. Reorder them and tell git to squash the appropriate ones:

^意味着之前的提交,所以这个命令说使用“a”之前的提交作为基础来rebase分支A。Git 将向您显示此范围内的提交列表。对它们重新排序并告诉 git 压缩适当的:

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

Now the history should look like this:

现在历史应该是这样的:

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

Now, let's grab the newly-squashed commit b+f for branchB.

现在,让我们为 branchB 获取新压缩的提交 b+f。

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

And the same for a+d+e+g for master:

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

git checkout master
git cherry-pick branchA^

Finally, update branchA so it points to c:

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

git branch -f branchA branchA^^

We should now have:

我们现在应该有:

    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)

Note that if you had multiple commits you wanted to move between branches, you could use rebase again (non-interactively):

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

Finally, a disclaimer: It's quite possible to reorder commits in such a way that some no longer apply cleanly. This could be because you chose a bad order (putting a patch before the commit introducing the feature it patched); in that case you'll want to abort the rebase (git rebase --abort). Otherwise, you'll have to intelligently fix the conflicts (just as you do with merge conflicts), add the fixes, then run git rebase --continueto move on. These instructions are also provided by the error message printed when the conflict occurs.

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

回答by Nelu

git rebase -i HEAD~3

Where 3is the number of commits that need reordering (source).

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

This will open vi, listing commits from oldest(top) to newest(bottom).
Now reorderthe lines, save, and exitthe editor.

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

ddpwill move current line down
ddkPwill move current line up(source)

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

回答by codeape

git rebase --interactiveis the command you want.

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

Example:

例子:

The current status is this:

目前的状态是这样的:

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

I want to reorder commits 9a24b81(Third commit) and 7bdfb68(Second commit). To do this, I first find the commit before the first commit we want to change. This is commit 186d1e0(First commit).

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

The command to execute is git rebase --interactive COMMIT-BEFORE-FIRST-COMMIT-WE-WANT-TO-CHANGE, in this case:

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

bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git rebase --interactive 186d1e0

This opens up a file in the default editor with the following contents:

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

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

Note that the ordering of commits in the file is opposite the one used for git log. In git log, the most recent commit is at the top. In this file, the most recent commit is at the bottom.

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

As the comment at the bottom of the file explains there are various things I can do, like squashing, dropping and reordering commits. To re-order commits, I edit the file so it looks like this (the bottom comments not displayed):

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

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

The pickcommand at the start of each line means "use (i.e. include) this commit" and when I save the temp file with the rebase commands and exit the editor, git will execute the commands and update the repository and working directory:

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

Note the rewritten commit history.

注意重写的提交历史。

Links:

链接:

回答by noisy

If you want to reorder only last two commits, you can you this git reorderalias: https://stackoverflow.com/a/33388211/338581

如果你只想重新排序最后两次提交,你可以使用这个git reorder别名:https: //stackoverflow.com/a/33388211/338581

回答by noisy

git rebaseis what you want. Check out the --interactive option.

git rebase就是你想要的。查看 --interactive 选项。