我如何将我最近的承诺转移到一个新的分支机构,并在这些承诺完成之前重新定义主? 例如:

master A - B - C - D - E

为此:

newbranch     C - D - E
             /
master A - B 

当前回答

这不是在技术上“移动”它们,但它有相同的效果:

A--B--C  (branch-foo)
 \    ^-- I wanted them here!
  \
   D--E--F--G  (branch-bar)
      ^--^--^-- Opps wrong branch!

While on branch-bar:
$ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range)

A--B--C  (branch-foo)
 \
  \
   D-(E--F--G) detached
   ^-- (branch-bar)

Switch to branch-foo
$ git cherry-pick E..G

A--B--C--E'--F'--G' (branch-foo)
 \   E--F--G detached (This can be ignored)
  \ /
   D--H--I (branch-bar)

Now you won't need to worry about the detached branch because it is basically
like they are in the trash can waiting for the day it gets garbage collected.
Eventually some time in the far future it will look like:

A--B--C--E'--F'--G'--L--M--N--... (branch-foo)
 \
  \
   D--H--I--J--K--.... (branch-bar)

其他回答

大多数以前的答案都是危险的错误!

不要这样做:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch

git reset --keep HEAD~3
git checkout -t -b newbranch
git cherry-pick ..HEAD@{2}

首先,它放弃了3个最新的承诺( - 保持像 - 硬,但更安全,因为它失败,而不是扔掉未承诺的变化)。 然后它放弃了新分支. 然后它将这些3个承诺返回新分支. 因为它们不再被一个分支提到,它这样做,使用 git 的回归: HEAD@{2} 是 HEAD 使用的承诺提到 2 个操作之前,即在我们 1 检查之前。

# newbranch will omit the 3 most recent commits.
git checkout -b newbranch HEAD~3
git branch --set-upstream-to=oldbranch
# Cherry-picks the extra commits from oldbranch.
git cherry-pick ..oldbranch
# Discards the 3 most recent commits from oldbranch.
git branch --force oldbranch oldbranch~3


技术解释

假设你分离起源 / 主,当它包含的承诺M1,M2,M3,然后做三个承诺自己:

M1--M2--M3  <-- origin/master
         \
          T1--T2--T3  <-- topic

但然后有人用强迫起源/大师重新编写历史,以删除M2:

M1--M3'  <-- origin/master
 \
  M2--M3--T1--T2--T3  <-- topic

M1--M3'  <-- origin/master
     \
      T1'--T2'--T3'  <-- topic (rebased)

因此,下列命令失败的原因:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch

但在这个特殊情况下,我们希望这些3个承诺被视为主题分支的一部分,为了实现这一点,我们需要在以前的修订中排除上流,这不包括3个承诺。

这里的大多数解决方案计算了你想回去的承诺数量,我认为这是一个错误的方法,计算需要计算。

你可以简单地通过你想要的承诺的承诺,或者换句话说,你想要的承诺是最后的承诺:

(重定向自Commit Hash)

为了避免这一点:

1) git checkout master

2) git branch <feature branch> master

3) git reset --hard <commit hash>

4) git push -f origin master

这不是在技术上“移动”它们,但它有相同的效果:

A--B--C  (branch-foo)
 \    ^-- I wanted them here!
  \
   D--E--F--G  (branch-bar)
      ^--^--^-- Opps wrong branch!

While on branch-bar:
$ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range)

A--B--C  (branch-foo)
 \
  \
   D-(E--F--G) detached
   ^-- (branch-bar)

Switch to branch-foo
$ git cherry-pick E..G

A--B--C--E'--F'--G' (branch-foo)
 \   E--F--G detached (This can be ignored)
  \ /
   D--H--I (branch-bar)

Now you won't need to worry about the detached branch because it is basically
like they are in the trash can waiting for the day it gets garbage collected.
Eventually some time in the far future it will look like:

A--B--C--E'--F'--G'--L--M--N--... (branch-foo)
 \
  \
   D--H--I--J--K--.... (branch-bar)

1) 创建一个新的分支,将所有更改转移到 new_branch。

git checkout -b new_branch

(二)然后回到旧的分支。

git checkout master

3、做吉·雷巴斯

git rebase -i <short-hash-of-B-commit>

4) 然后打开的编辑器包含最后3个承诺信息。

...
pick <C's hash> C
pick <D's hash> D
pick <E's hash> E
...

5) 更改选项下载所有这些 3 任务. 然后保存并关闭编辑器。

...
drop <C's hash> C
drop <D's hash> D
drop <E's hash> E
...

6) 现在最后3个命令从当前分支(主)中移除。 现在强烈推分支,在分支名称之前 + 标志。

git push origin +master

要做到这一点,而不重写历史(即如果您已经推出了承诺):

git checkout master
git revert <commitID(s)>
git checkout -b new-branch
git cherry-pick <commitID(s)>

那么,两支分支都可以在没有武力的情况下被推动!