如何从基于基础的分支重新设置基础?

我的历史是这样的:

主人 \ A \ O B

那么,解释一下:

  • 我有从 master开始的 A分支
  • 我有一个从 A开始的分支 B(只有1个提交)

我想要的是:

主人 \ A \ O B


我所做的是:

1).

Git 收银台 Git rebase master

这导致了大量的冲突,经过一段时间的修正,以下历史出现了:

主人 \ A

这正是我想要的。

(我不知道 B现在在哪里)


2).

在这之后,我做了很多壁球和改变了提交的顺序对 A,使历史看起来像我想要的。


3).

现在,我还想做的是:

Git 收银台 B Git rebase A

然而,这似乎不工作,我不知道为什么。如果我执行 git log,我会看到在我执行步骤1之前就已经存在的提交。

此外,我还得到了在第1步中已经解决的大量冲突。我花了很多时间做这件事,不想再做了。

这个例子 建议使用 --onto,我就是这么做的:

Git 收银台 B Git rebase ——到 A 上

但是这会完全删除 B上的提交,使得 AB指向相同的提交,即 A上的最后一个提交。


我的问题是: 我怎样才能有效地将 B 从 A 重新定位,使它看起来像是 B 从 A 开始的? (一开始确实是这样的)。

我最好的猜测是我使用的 --onto是错误的,或者我应该使用其他的东西(比如 cherry-pick)。

14162 次浏览

If you have already re-based A. It should be the case that B is exactly where you left it. The branch (a pointer) that was A has simply moved to it's new location.

What I would recommend to effectively rebase B onto A is, as you suggested, to use 'cherry-pick'. This command attempts to apply the changes made in a commit to the branch on which you run it.

So if the commit IDs of the commit to which B originally pointed was '123456' then I would recommend moving your current 'B' to the same place as the new 'A' with git branch -f B A then run git cherry-pick 123456 which will apply the changes onto A.

I believe the --onto flag is used to set the target location from which to apply the commits.It defaults to "upstream" (source: http://git-scm.com/docs/git-rebase).

The way I like to think of the rebase command is as follows:

git rebase --onto <Starting here> <Apply all commits from HERE> <TO HERE>

Using this, it would probably have been simpler to rebase B onto master, then point A to the commit preceding B.

git rebase master B

(as the start point (--onto) is implicitly 'master')

then to use git branch -f A B^ (the ^ means 'the parent of')

Short answer to How can I effectively rebase B off A so that it looks like B started from A? Assuming you want to move exactly one commit:

git rebase --onto A B~ B

If you want to move more then one commit use:

git rebase --onto A old_A B

The rest of the answer.

Your branch of B is still around (you can check it out), but its parent is still the exact commit object that A was before.
to see a graphical representation of this I use:

git log --graph --decorate --all

to see all branches and where they are with respect to each other.

What you originally had:

o---o---o---o  master
\
o---o---o  A
\
o B

What you have now:

o---o---o-----------o  master
\               \
o---o---o(B~)   o---o---o A
\
o B

In terms of using --onto, you need to have a starting point and an ending point. use:

git rebase --onto [target] [rebasing stops] [rebasing head]
git rebase --onto A B~ B

And what you get:

o---o---o----------o  master
\              \
o---o---o      o---o---o A
(old_A)           \
o B

[branch_name]~ indicates the parent commit of the branch.

The B~ is the branch that you do not want to change. (It happens to be the old A)

Alternatively, if B was the only commit that had A as a parent, (i.e., B is the end of a chain of commits that branch off master) you could do

git checkout B
git rebase master
git checkout B~   # this is the commit before B (the A commit)
git branch -d A   # remove the old A branch (it was rebased, and so is now invalid
git branch A      # recreate the A branch on the commit that is based on the original A

I have the same issue of my git flow, and I found a best and fast way to do it.

(1) Project history in the beginning:

    master ---A---B---C
\
D---E---F feature1
\
G---H feature2

(2) Rebase feature1 onto master and force pushed:

    master ---A---B------------------------C
\                           \
D---E---F feature1(old)     D---E---F feature1
\
G---H feature2

(3) Rebase feature2 onto featrue1 (the new one)

    master ---A---B------------------------C
\
D---E---F feature1
\
G---H feature2

The most confused part is how to do (3) .. but no one has a clear answer of doing it.

I believe many people encountered the same issue as I did, when we were trying to do "rebase --onto", we found that feature1(old) is actually not existing!

    git rebase --onto feature1 feature1(old) feature2

Solution is to use below instead:

    git rebase --onto feature1 feature1@{1} feature2

The syntax feature1@{1} means "the last known state of feature1 before the rebase", answer is refereed from https://coderwall.com/p/xzsr9g/rebasing-dependent-branches-with-git