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

时间:2008-12-12 19:45:17

标签: 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"

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

8 个答案:

答案 0 :(得分:61)

好吧,我觉得这个分支被称为“特征”,它是从“主人”分支出来的。

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

git merge-base feature master

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

git rebase -i `git merge-base feature master`

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

答案 1 :(得分:52)

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

git rebase -i XYZ

您只能从第二次提交开始重新定位。

如果你想从第一次提交中进行重新定位:

git rebase -i --root

答案 2 :(得分:38)

您是否尝试过:git rebase -i master

答案 3 :(得分:20)

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

git rebase -i <the SHA hash of the root commit>

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

gitx screencap

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

git rebase -i 38965ed29d89a4136e47b688ca10b522b6bc335f

我的编辑弹出这个,我可以重新排列/挤压/随意随意。

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

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

编辑:这就是魔术:

git log master..other_feature | cat

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

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

git rebase -i  `git log master..other_feature --pretty=format:"%h" | tail -n 1`~

答案 4 :(得分:7)

来自其他分支的重新定位问题

git rebase -i master的问题在于,您可能会遇到目前尚未想要处理的合并冲突,或者您可能会在一次提交中修复冲突,只能在在rebase过程中再次提交。

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

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

更好的方法

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

rbi = !sh -c \"git rebase -i `git merge-base $1 HEAD`\" -

<强>用法

git rbi parentBranch

工作原理

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

答案 5 :(得分:4)

从Git v1.7.10开始,你可以在没有参数的情况下运行git rebase,它会找到fork point并在上游分支上重新定位你的本地更改。

您需要配置上游分支才能工作(即git pull无参数应该有效。)

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

  

如果未指定,则配置上游   branch..remote和branch.merge选项将被使用(见   git-config [1]详细信息)和--fork-point选项被假定。如果   您目前不在任何分支机构或当前分支机构没有   如果配置了上游,则rebase将中止。

答案 6 :(得分:2)

一般解决方案(如果您不知道上游分支的名称)是:

git rebase -i @{upstream}

请注意,如果您的上游(可能是跟踪分支)自上次重新定位后已更新,您将从上游提取新的提交。如果您不想提交新提交,请使用

git rebase -i `git merge-base --all HEAD @{upstream}`

但这有点拗口。

答案 7 :(得分:1)

git rebase -i --onto @{u}... @{u}

从HEAD及其上游的单个合并点开始的交互式rebase,包括HEAD中不在其上游的所有提交。

换句话说,就是你想要的。