如何使用'git rebase -i'来重新分支分支中的所有更改?

sem*_*s99 59 git

这是一个例子:

>git status
# On branch master
nothing to commit (working directory clean)
>git checkout -b test-branch
>vi test.c
>git add test.c
>git commit -m "modified test.c"
>vi README
>git add README
>git commit -m "modified README"
Run Code Online (Sandbox Code Playgroud)

现在我想做一个' git rebase -i',这将让我为这个分支重新提交所有提交.有没有像' git rebase -i HEAD~MASTER'或类似的东西.我想我可以做' git rebase -i HEAD~2',但我真的不想计算已经提交了多少次提交.我也可以这样做git rebase -i sha1但我不想通过git log来查找第一个提交sha1.有任何想法吗?

小智 65

好吧,我认为分支被称为"特征",它从"主"分支.

有一个叫做merge-base的小git命令.它需要两次提交,并为您提供这两者的第一个共同祖先.所以...

git merge-base feature master
Run Code Online (Sandbox Code Playgroud)

...将为您提供这两个提交的第一个共同祖先.猜猜当你将这个提交传递给git rebase -i时会发生什么,比如......

git rebase -i `git merge-base feature master`
Run Code Online (Sandbox Code Playgroud)

来自master和feature分支的第一个共同祖先的交互式rebase.利润!;)

  • 与许多git解决方案相比,这是非常好的:). (13认同)
  • 我建议使用`git merge-base master HEAD`,它应该始终适用于当前分支而不键入当前分支名称.别名这个命令,你有你的短的git命令. (6认同)
  • 虽然它很丑 - 手头没有语法糖吗? (4认同)
  • `git rebase -i $(git merge-base @ {u} HEAD)` - 假设您当前的分支设置为跟踪基本分支.示例:`git branch feature1 origin/master`将跟踪origin/master.所以现在你甚至不必输入它. (3认同)

Joo*_*oer 56

所有提供的解决方案的问题是,它们不允许您从第一次提交时进行rebase.如果第一个提交哈希值是XYZ,那么您执行以下操作:

git rebase -i XYZ
Run Code Online (Sandbox Code Playgroud)

您只从第二次提交开始重新绑定.

如果你想从第一次提交改变:

git rebase -i --root
Run Code Online (Sandbox Code Playgroud)

  • 但是" - root"会从第一次提交*而不是第一次提交而不是第一次提交,这是OP要求的 (13认同)
  • 我相信这是正确的答案. (7认同)

idi*_*dak 42

你试过了git rebase -i master吗?

  • 如果主服务器位于分支中的当前合并库之前,则会失败. (19认同)
  • `git rebase -i master`的问题是你可能有合并冲突,你现在不一定要处理,或者你可能在一次提交中修复冲突,只是在另一次提交时再次修复它变革的过程.我添加了一个答案,提供了替代方案,并且可以选择指定确切的提交或者要从中进行重新绑定的提交数量. (4认同)

Ott*_*tto 20

在其他平台上使用gitk(*nix)或gitx(OS X)或类似的东西,并查看哪个提交是您的分支的根目录.然后运行:

git rebase -i <the SHA hash of the root commit>
Run Code Online (Sandbox Code Playgroud)

例如,我有一个我使用gitx检查的存储库:

gitx screencap

现在我知道根哈希我可以运行这个:

git rebase -i 38965ed29d89a4136e47b688ca10b522b6bc335f
Run Code Online (Sandbox Code Playgroud)

我的编辑弹出这个,我可以重新排列/挤压/随心所欲.

pick 50b2cff File 1 changes.
pick 345df08 File 2 changes.
pick 9894931 File 3 changes.
pick 9a62b92 File 4 changes.
pick 640b1f8 File 5 changes.
pick 1c437f7 File 6 changes.
pick b014597 File 7 changes.
pick b1f52bc File 8 changes.
pick 40ae0fc File 9 changes.

# Rebase 38965ed..40ae0fc onto 38965ed
#
# Commands:
#  pick = use commit
#  edit = use commit, but stop for amending
#  squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Run Code Online (Sandbox Code Playgroud)

我确信有一些神奇的方法来说服git自动找出树的根,但我不知道它是什么.

编辑:这就是魔术:

git log master..other_feature | cat
Run Code Online (Sandbox Code Playgroud)

这将显示该分支上的所有提交,并且对cat的管道将禁用寻呼机,以便您立即看到第一个提交.

编辑:结合上面提供了一个完全自动化的解决方案:

git rebase -i  `git log master..other_feature --pretty=format:"%h" | tail -n 1`~
Run Code Online (Sandbox Code Playgroud)

  • -1 OP说他不想通过日志搜索 (5认同)

Set*_*ers 7

从不同的分支重新定位的问题

问题git rebase -i master在于您可能存在目前不一定要处理的合并冲突,或者您可能在一次提交中修复冲突,只在rebase过程中再次在另一次提交中修复它.

从已知提交重新定位的问题

这里的整个问题是你必须知道你要引用哪个提交,无论是通过它的SHA,还是HEAD~x等.这只是一个小麻烦,但这是一个烦恼.

更好的方法

如果您想要重新绑定当前分支中的所有提交,因为它与其父分支共享的最新提交,您可以将以下别名添加到.gitconfig:

rbi = !sh -c \"git rebase -i `git merge-base $1 HEAD`\" -
Run Code Online (Sandbox Code Playgroud)

用法

git rbi parentBranch
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

这个别名只是一个shell脚本,它使用一个引用父分支的参数.传入该参数是git merge-base为了确定该分支与当前分支之间的最新共享提交.


Mat*_*Moy 6

从 Git v1.7.10 开始,您可以git rebase不带参数运行,它会找到分叉点并在上游分支上重新设置您的本地更改。

您需要配置上游分支才能使其工作(即git pull不带参数应该工作)。

有关更多详细信息,请参阅git rebase的文档:

如果未指定,则将使用在branch..remote和branch..merge选项中配置的上游(有关详细信息,请参阅git-config [1])并假定使用--fork-point选项。如果您当前不在任何分支上或者当前分支没有配置上游,则变基将中止。