Git 从特定提交开始创建新分支
我想创建一个新分支,从某个提交开始。然而,我希望所有随后提交的提交也成为该分支的一部分 假设这是带有所有提交的Git 从特定提交开始创建新分支,git,version-control,branch,commit,git-commit,Git,Version Control,Branch,Commit,Git Commit,我想创建一个新分支,从某个提交开始。然而,我希望所有随后提交的提交也成为该分支的一部分 假设这是带有所有提交的分支-D > branch-D commit-A ---- commit-B ---- commit-C ---- commit-D 我想删除从commit-B到新的branch的所有内容,让我们将其命名为branch-C,并且只保留commit-a在branch-D > branch-D commit-A > branch-C commit-B ---- comm
分支-D
> branch-D
commit-A ---- commit-B ---- commit-C ---- commit-D
我想删除从commit-B
到新的branch
的所有内容,让我们将其命名为branch-C
,并且只保留commit-a
在branch-D
> branch-D
commit-A
> branch-C
commit-B ---- commit-C ---- commit-D
我还没有将任何内容推送到远程存储库。
有什么方法可以做到这一点吗?最直接的方法是在提交a之前在提交的基础上创建2个新分支。然后cherry pick提交a到1个分支,cherry pick提交B、C,D到第二个分支。最直接的方法是在提交A之前在提交的基础上创建两个新分支。然后cherry pick提交A到1个分支,cherry pick提交B、C、D到第二个分支。更新-我误读了您的图表,结果混淆了分支名称。正如torek所指出的,对图表进行“更正确”的阅读也会有一些含糊不清的地方。我将保留我的答案,因为我相信它传达了主要的原则;如果您需要进一步编辑
branchC
history,我将介绍如何使用rebase;但要获得更详细的答案,请参阅torek的回复
首先,让我谈谈我认为您正在寻找的解决方案;但我建议阅读更多,因为这个问题中存在概念上的混乱,值得澄清 那么你现在有了
A -- B -- C -- D <--(branchD)
然后将branchD
分支移回A
git reset --hard HEAD~3
(我使用了HEAD~3
,因为在本例中,这将是A
的一个名称。这取决于从master
的历史记录中执行的提交次数。使用A
的提交ID(SHA)代替HEAD~3
总是可以的)
完成这些步骤后,您就可以
A <--(branchD)
\
B -- C -- D <--(branchC)
这里,branchD^
是“在a
之前提交”的可能名称。如果有这样的提交,它可能有其他名称-可能是master
,或者肯定是它的提交ID。如果没有这样的提交,那么我想你可以说
git rebase -i branchD^ branchC
git rebase -i --root branchC
(但在这种情况下,试图从分支历史中删除A
可能毫无意义,因此我怀疑这就是发生的情况)
rebase命令将打开一个文本编辑器,其中包含一个TODO列表,每个提交都有一个条目。您可以从列表中删除提交a
的条目,然后保存并退出。这不会干扰branchD
-它仍将指向a
-但它将通过复制B
为branchC
创建一个新的历史记录>,C
和D
。那么您就可以
x -- B' -- C' -- D' <--(branchC)
\
A <--(branchD)
x--B'--C'--D'更新-我误读了您的图表,结果混淆了分支名称。正如托雷克所指出的,对您的图表进行“更正确”的阅读会有一些含糊不清的地方。我将保留我的大部分答案(但要理顺分支名称)我相信它传达了主要原则;如果您需要进一步编辑branchC
history,我将稍微介绍一下如何使用rebase;但要了解更详细的答案,请参阅torek的回复
首先,让我来谈谈我认为你在寻找的解决方案;但我建议阅读更多的内容,因为这个问题中存在概念上的混乱,值得澄清
那么你现在有了
A -- B -- C -- D <--(branchD)
然后将branchD
分支移回A
git reset --hard HEAD~3
(我使用了HEAD~3
,因为在本例中,这将是A
的一个名称。这取决于从master
的历史记录中执行的提交次数。使用A
的提交ID(SHA)代替HEAD~3
总是可以的)
完成这些步骤后,您就可以
A <--(branchD)
\
B -- C -- D <--(branchC)
这里,branchD^
是“在a
之前提交”的可能名称。如果有这样一个提交,它可能有其他名称-可能是master
,或者肯定是它的提交ID。如果没有这样的提交,那么我想你可以说
git rebase -i branchD^ branchC
git rebase -i --root branchC
(但在这种情况下,试图从分支历史中删除A
可能毫无意义,因此我怀疑这就是发生的情况)
rebase命令将打开一个文本编辑器,其中包含一个TODO列表,每个提交都有一个条目。您可以从列表中删除提交A
的条目,然后保存并退出。这不会干扰branchD
——它仍然指向A
——但它将通过复制B
、C
和D
为branchC
创建一个新的历史记录。那么你会
x -- B' -- C' -- D' <--(branchC)
\
A <--(branchD)
x--B'--C'--D'Git的奇特之处在于,分支名称不会影响提交历史记录中的内容,只会让您和其他人找到提交,这一点非常重要。秘密在于,在Git中,提交可能同时发生在多个分支上
但重要的是,一旦做出承诺,任何承诺都无法改变。可以将其复制到(新的,略有不同的)提交,但不能更改
此外,虽然可以强制任何分支名称指向任何提交,但分支名称运动有一个“正常方向”:通常,它们只前进。正如我们稍后将看到的,前进意味着无论他们过去指的是什么承诺,仍然“在”那个分支上。因此,一旦您将您的提交给了其他人一些其他Git,并要求他们调用这些提交branch-D
,就很难让其他Git收回这些提交。因此:
我还没有将任何内容推送到远程存储库。有办法做到这一点吗
是的,可能有一个非常简单的方法:“还没有推送任何东西”意味着你是唯一一个有这些提交的人,所以无论如何
git reset --hard <hash-of-A> # move current branch; re-set index and work-tree
git branch -f branch-D <hash-of-A> # force branch-D to point to A
git checkout -b branch-C master
...--o--o <-- branch-C (HEAD), master
\
A--B--C--D <-- branch-D
git cherry-pick branch-D~3..branch-D
B'-C'-D' <-- branch-C (HEAD)
/
...--o--o <-- master
\
A--B--C--D <-- branch-D
git branch -f branch-D branch-D~3
git branch -f branch-D <hash-of-A>
git checkout hashOfCommitA
git checkout -b NewBranchName
git checkout nameOfFirstBranch
git revert hashOfCommitA