2015-09-28 134 views
1

我创建了一个本地分支(git checkout -b),其中我做了一些脏提交(“WIP”等)。我从来没有推到遥远的地方。我现在想推前一些提交重命名/壁球:Git rebase一个没有远程的本地分支

$ git rebase -i 
There is no tracking information for the current branch. 
Please specify which branch you want to rebase against. 
See git-rebase(1) for details 

    git rebase <branch> 

If you wish to set tracking information for this branch you can do so with: 

    git branch --set-upstream-to=origin/<branch> feature/position-preview 

话,我的建议:

$ git branch --set-upstream-to=origin/feature/my-feature feature/my-feature 
error: the requested upstream branch 'origin/position-preview' does not exist 
hint: 
hint: If you are planning on basing your work on an upstream 
hint: branch that already exists at the remote, you may need to 
hint: run "git fetch" to retrieve it. 
hint: 
hint: If you are planning to push out a new local branch that 
hint: will track its remote counterpart, you may want to use 
hint: "git push -u" to set the upstream config as you push. 

的事情是,我不想push -u,因为它是,因为它会导致不良的历史。

如何重新绑定我的新本地分支?

回答

0

Git的文档的muchderision主题...有很好的理由:

git的变基[-i | --interactive] [选项] [--exec <CMD>] [--onto <newbase>] [<上游> [<分支>]]

此处该参数被标记upstream,和有帮助的( ?)从命令输出参考git branch --set-upstream-toorigin/<branch>,这意味着您的本地分支必须有一个像origin/my-feature这样的远程分支才能工作。但事实并非如此。

git rebase做什么是副本一系列提交,每个拷贝发生,如果你想在一个特定的运行git cherry-pick提交。通过复制每提交一个线性提交图中的提交,您将获得复制开发分支的效果。 我认为,这使得以图表形式更有意义。例如,假设你有这样的顺序:

... <- o <- A <- B <-- master 
     \ 
      C <- D <- E <-- my-feature 

其中每个字母代表一些特定的承诺,其中一个大丑40个字符的SHA-1的数和提交历史my-feature与commit-连接起来master的历史记录在提交o。如果您在master上创建了新分支my-feature,然后又回到分支master,进行了两次提交,然后转至my-feature并进行了三次提交(每次提交的实际顺序)无所谓:我只需要你在master上做了两个,现在我把他们作为现在作为第一个A和第二个B,并且在my-feature上有三个。现在

,因为它与发展情况,你可能会决定它将使基础上,master当前提示,即更有意义C -through- E,有C的父提交是B

一个非常手动的方法来实现这一目标是:

$ git checkout master 
$ git checkout -b new-my-feature 
$ git cherry-pick <id of commit C> 
$ git cherry-pick <id of commit D> 
$ git cherry-pick <id of commit E> 

这使得一个新的分支,new-my-feature,并复制三个提交,这个结果:

   C' - D' - E' <-- new-my-feature 
      /
... o - A - B <-- master 
     \ 
     C - D - E <-- my-feature 

的方式混帐构造新的提交C'将比较树 - 关联的源快照 - 对于C与其父提交o的树,将相同的更改应用于t ree for B,然后重新使用提交消息C进行新的提交。换句话说,提交C'C的“副本”。 D'D相同,E'E相同。

在任何情况下,如果你把这个第三图像,然后删除my-feature分支标签,并重新命名new-my-featuremy-feature,你得到的是:

   C' - D' - E' <-- my-feature 
      /
... o - A - B <-- master 

原来的三所老my-feature提交的“丢失“(他们通过”reflog“条目保存30天,但这些条目通常不可见,以免混淆视图)。

git rebase所做的是自动执行此过程:它找到要复制的提交序列,将序列复制到其他提交中,然后移动分支标签。

你可以指定的是,所有没有非常好记录的选项都是分支名称 - 默认为当前分支 - 通常在某种程度上,间接地指向停止复制的点。 “目标”提交,重定位为--onto <newbase>,默认为您给出的参数(如果有的话),请拨打<upstream>

这种工作方式依赖于理解其他相当重要的东西,这会影响双点符号。

让我们回到原来的图形,我们再次做任何樱桃采摘和分支标签移动的,也就是说,之前我们变基之前有:

... - o - A - B <-- master 
     \ 
      C - D - E <-- my-feature 

现在让我们来问git的是什么版本在master..my-feature

$ git rev-list master..my-feature 
e59f6c2d348d465e3147b11098126d3965686098 
8413a79e67177d026d2d8e1ac66451b80bb25d62 
1f9e0a53489aaca7859722e037a47e93858cbc42 

(我做这些,但事实上这种设置,你会真正得到只有三个SHA-1)。

我认为一个很好的方式来解释这是在颜色填充/突出显示(当然,我不能在这里的文字做这个,所以你必须想像它)。

想象一下,您从my-feature的提示开始,即提交E。将此提交涂成绿色:这是“要使用”。然后,按照其父指针返回提交D。将此提交也刷为绿色。跟着那个到C并且涂绿色;跟着那个到o并且绘制那个绿色,然后继续到整个图形中的o的父母。

然后,从master的提示开始,即提交B。将此提交涂成红色:“停止”。然后,按照其父母提交A,并将其涂成红色。按照o,用红色油漆在绿色涂料上涂漆:“停止”。一路跟随o的父母,用红漆覆盖他们所有的绿色涂料。

(如果你愿意,你可以做红的第1,那么绿,只要你覆盖任何红配绿。)

结果,将提交该git rev-list应该列出,正是那些(仍然)是绿色的提交,这只是我们想要改变的三个提交。即使我们从Bmaster的提示开始了“红色列表”,情况也是如此。

所有这一切的简短版本是,为了重组,我们想要的 - 至少现在 - 是git rebasemaster视为“上游”。 rebase的“上游”参数提供了“红色颜料”参数,master..my-feature修订说明符的左半部分--onto参数:我们想要复制提交,以便它们在master的提示最后提交后出现。

实际上,您可以使用git branch --set-upstream-tomaster(在您自己的私人存储库中)设置为my-feature的“上游”。上游不一定是像origin/branch这样的远程跟踪分支。您自己的本地分支机构在此处可以正常工(但是请记住,如果您开始共享此分支 - 将其推送到远程git存储库(如origin),那么您可能希望在此时开始使用远程跟踪分支作为“上游”,以提醒自己要分享,并获得了较为典型的变基流去。你可以做一个新的git branch --set-upstream-to在任何时候改变“上游”。)


单词“分支”的另一个git文档问题的例子。它至少有两种不同的含义。在作为该脚注段落的一部分的图表中,master是一个“分支”(我喜欢称其为“分支标签”或“分支名称”)。同样,my-feature是一个分支。在这种情况下,这两种标签分别简单地标注一个特定的提交 - BE。但是,每个提交都有其自己的父提交指针:B指向AE指向D,依此类推。遵循这些父指向箭头产生的提交链也是一个“分支”。

在其确切点停止调用此类链“分支”取决于你的观点:my-feature可能会停止在提交o,而master可能会继续回通过o。 Git在这里并没有太多的帮助,尽管没有总是正确的答案:它确实取决于你想包含的内容。

有做这一个稍微更简单的方法,因为不是一个承诺作为参数git cherry-pick可以采取更多:

$ git cherry-pick <id> <id> <id> 

例如,或者:

$ git cherry-pick my-feature~3..my-feature 

它使用在the gitrevisions documentation中描述的说明符可以让git找到这三个ID。

1

事情是,没有参数默认情况下rebase提议从最后一次提交推送rebase。不过,我们可以轻推它在正确的方向:

git rebase -i <hash> 

选择提交前夕<hash>你想在历史中看到的。这些哈希值可以通过git log获得。

+1

像'HEAD〜1'(在最后一次提交之前提交)这样的表达式也应该有效。如果有足够的提交,它可能会更容易复制并粘贴来自日志的散列,而不是计算您想要改变的提交数量。 – CoDEmanX

相关问题