Git 移动在其上创建分支的内容
好吧,就这么定了。我在commit(2f6ea37)的基础上创建了一个分支(master),然后在master的基础上创建了另一个分支(development)。对开发进行了更改。问题是,实际上应该根据以前的提交(df7992e)而不是(2f6ea37)创建master 我如何在不失去致力于开发的新东西的情况下改变master的创建位置 现在是这样的:Git 移动在其上创建分支的内容,git,branch,rebase,Git,Branch,Rebase,好吧,就这么定了。我在commit(2f6ea37)的基础上创建了一个分支(master),然后在master的基础上创建了另一个分支(development)。对开发进行了更改。问题是,实际上应该根据以前的提交(df7992e)而不是(2f6ea37)创建master 我如何在不失去致力于开发的新东西的情况下改变master的创建位置 现在是这样的: branch1 --> <2f6ea37> --> <df7992e>
branch1 --> <2f6ea37> --> <df7992e>
\
master
\
develop --> <new_commit>
branch1-->
\
主人
\
开发-->
以下是它应该是什么样子:
branch1 --> <2f6ea37> --> <df7992e>
\
master
\
develop --> <new_commit>
branch1-->
\
主人
\
开发-->
TL;博士
您可能只需要三个git branch-f
命令即可完成所需操作:
git branch -f master 2f6ea37
git branch -f branch1 df7992e
git branch -f develop 2f6ea37
但要使用git branch-f
执行此操作,必须使用除这三个分支名称之外的其他分支名称,因此可能需要一个git reset--hard
或其他命令。如果develope
已经有了额外的提交,那么您就有了更大的问题。请参阅下面的详细说明
长的
首先(这有点小,但确实很重要),图表中的箭头是错误的,因为它们是向前的。:-)Git做任何事情都是反向的。因此,类似于df7992e
的提交将向后指向其前身2f6ea37
像master
和develope
这样的分支名称只包含一个原始散列ID,即它们直接指向特定的提交。所以我把它画成:
2f6ea37 <-- branch1
\
df7992e <-- master
\
C <-D <-E <-- develop
现在,Git中关于分支名称的事情是,您总是可以在任何分支名称中填充新的哈希ID。该分支现在直接指向您给它的哈希ID
随着时间的推移,分支名称的移动方式是累积新的提交:
A--H <-- branch1
\
B--F--G <-- master
\
C--D--E--I <-- develop
但如果我们将其与刚才的状态进行比较,则名称master
已朝“错误”的方向移动。它过去称为commitB
,现在改为commitA
。名称branch1
已向“右”方向移动(向前,与内部向后箭头相对)
如果其他Git存储库(和/或其用户)以前见过您的master
标识提交B
,那么像这样向后移动分支名称会使他们感到困惑。记住,任何地方的所有Git都共享原始哈希ID,因此,如果任何其他Git有commitB
,它们可能会让一些名称记住它。他们可能会让自己的origin/master
指向共享提交B
的副本,因此,他们可能也会让自己的master
指向B
如果没有其他人见过,你很好。只需使用git branch-f
和/或git reset--hard
将正确的哈希ID填充到正确的分支名称中
这里潜在的大麻烦
最后一个问题是分支名称develope
。在这里,我把它画成指向commitE
,其中E
指向D
,它指向C
,它指向B
我相信,目前根据你绘制初始图表的方式,你真正拥有的更像这样:
A <-- branch1
\
B <-- master, develop
如果您现在git checkout develope
并进行新的提交C
,新的C
将指向a
:
C <-- develop (HEAD)
/
A <-- master
\
B <-- branch1
这里的问题是现有提交C
已经指向现有提交B
。一旦提交,任何提交的任何内容都无法更改。因此,您根本无法更改C
。在这种情况下,您必须将C
,以及D
和E
复制到新的和改进的提交中。新的和改进的是,新的C
——我们称之为C'
——指向A
,并使用A
作为其源代码库。类似地,新的D'
指向C'
,新的E'
指向D'
,这给了我们:
C'-D'-E' <-- develop (HEAD)
/
A <-- branch1
\
B <-- master
\
C--D--E [abandoned]
它使用原始散列ID表示排除提交B
和更早版本,从当前提交向后复制所有提交,新提交在提交2f6ea37
之后。然后移动名称develope
,指向上次复制的提交。排除意味着要复制的提交集正好是正确的集-C-D-E
,因此我们得到了上面所画的内容
现在是时候使用两个git branch-f
命令来交换另外两个分支名称了,而我们仍在开发中。或者,我们可以在启动git-rebase
之前交换它们
如果您没有要复制的提交C-D-E
,但正在进行develope
,该怎么办?
假设现在的实际图片可以这样绘制:
A <-- branch1
\
B <-- master, develop (HEAD)
使用git branch-f develope
会给您一个错误:
fatal: Cannot force update the current branch.
但是您仍然需要移动开发。有很多方法可以做到这一点:
- 使用
git-rebase
:git-rebase--on-master branch1
:这排除了从B
向后开始的提交,即从复制开始的所有提交;将零提交复制到提交A
之后;然后将当前分支名称移动到提交A
的点
- 使用
git reset
:git reset--hard master
:这将丢弃索引和工作树中所有正在进行的工作,将它们重新设置为与提交A
匹配,并将当前分支名develop
移动到提交A
的位置。这样做的好处是它快速、简单,并且可以做你想做的事情。缺点是它会抹去任何正在进行的工作
A <-- branch1
\
B <-- master
\
C--D--E <-- develop (HEAD)
C'-D'-E' <-- develop (HEAD)
/
A <-- branch1
\
B <-- master
\
C--D--E [abandoned]
git rebase --onto 2f6ea37 df7992e
A <-- branch1
\
B <-- master, develop (HEAD)
A <-- master
\
B <-- branch1, develop (HEAD)
fatal: Cannot force update the current branch.