我如何使用“git rebase -i”来重定义分支中的所有更改?

这是一个例子:

>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 ',但是我真的不想去计算已经做了多less次提交。 我也可以做' git rebase -i sha1 ',但我不想通过git log查找第一个提交sha1。 有任何想法吗?

你有没有尝试过: git rebase -i master

好吧,我假设分支被称为“function”,它是从“主”分支。

有一个叫做merge-base的小git命令。 它需要两个提交,并给你这两个的第一个共同的祖先。 所以…

 git merge-base feature master 

…会给你这两个承诺的第一个共同的祖先。 猜猜当你把这个提交给git rebase -i时会发生什么,就像…

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

来自主人和function分支的第一个共同祖先的交互式重新分配。 利润! ;)

所有提供的解决scheme的问题是,它们不允许您从第一次提交开始重新分配。 如果第一个提交散列是XYZ,你可以这样做:

 git rebase -i XYZ 

你只从第二次提交开始。

如果您想从第一次提交中进行重定位,请执行以下操作:

 git rebase -i --root 

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

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

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

gitx screencap http://img.skitch.com/20081213-mq7qpp5nhceksdhfx14rerjgyx.jpg

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

 git rebase -i 38965ed29d89a4136e47b688ca10b522b6bc335f 

而我的编辑popup这个,我可以重新排列/压扁/任何我喜欢的。

 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 

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

编辑:结合上述提供了一个完全自动化的解决scheme:

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

由于Git v1.7.10,你可以运行没有参数的git rebase ,它会在上游分支上findfork point和rebase局部变化。

你需要configuration上游分支为此工作(即没有参数的git pull应该工作)。

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

如果没有指定,将使用在branch..remote和branch..merge选项中configuration的上游(参见git-config [1]了解详细信息),并假定–fork-point选项。 如果您当前没有在任何分支上,或者当前分支没有configuration上游,那么rebase将会中止。

来自不同分支的rebase的问题

git rebase -i master的问题在于你可能合并了目前不一定需要处理的冲突,或者你可以在一次提交中修复冲突,而只是在修改过程中再次修复冲突的rebase。

来自已知提交的rebase的问题

这里的全部问题是,你必须知道你必须引用哪个提交,无论是SHA,还是HEAD〜x等。这只是一个小小的烦恼,但这是一个烦恼。

更好的方法

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

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

用法

 git rbi parentBranch 

怎么运行的

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

一个通用的解决scheme(如果你不知道上游分支的名字)是:

 git rebase -i @{upstream} 

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

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

但是这有点儿一口。

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

从HEAD和它的上游的单个合并点开始交互式重新分配,包括所有不在其上游的提交。

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