在修改了从公共存储库克隆的存储库的master分支之后,我创建了许多从修改后的master分支派生的功能分支。
现在我注意到,对于我要进行的一些新更改,不需要对master分支进行修改。
因此,我想将我的master分支还原为原来的未更改克隆master。而且,我想创建一个中间分支,其中包含我当前对主分支所做的更改。
同时,我想保留已经推送到远程存储库的功能分支。 (我也已经推送了修改后的master分支。)
要实现这一目标需要采取哪些步骤?
答案 0 :(得分:0)
根本不需要做任何事情,但是如果您希望做某事,我建议您做些其他事情。
在Git中,分支名称对Git本身意义不大。重要的是 commits 。 (当然,这些名称对人类很重要。)
商品通过其丑陋的哈希ID进行唯一标识。这些似乎是随机的,对人类来说几乎没有用,因此出于绘画目的,让我们在这里使用单个大写字母。
您从一个具有一系列提交的克隆开始,以一个我们称为H
的提交结束,而不是使用其实际哈希值:
...--F--G--H <-- master (HEAD), origin/master
然后,您在master
上添加了自己的几个新提交。每个人都有一个新的大的丑陋哈希ID,我们将其替换为下一个字母:
...--F--G--H <-- origin/master
\
I <-- master (HEAD)
进行一次新的提交会告诉Git:请移动当前分支,即附加了HEAD
的分支,以指向该新的提交,指向其先前的提交。现在,master
个名称将提交I
,不再提交H
。不过,提交I
会记住H
的哈希。如果再提交两次,则图片变为:
...--F--G--H <-- origin/master
\
I--J--K <-- master (HEAD)
在这一点上,您创建了功能分支-让我们来绘制一下:
...--F--G--H <-- origin/master
\
I--J--K <-- master (HEAD), feature1, feature2
然后,通过将feature
附加到其上的HEAD
分支之一来创建新的提交。让我们选择feature1
:
...--F--G--H <-- origin/master
\
I--J--K <-- master, feature1 (HEAD), feature2
接下来,您创建了一个或两个提交:
...--F--G--H <-- origin/master
\
I--J--K <-- master, feature2
\
L--M <-- feature1 (HEAD)
也许,接下来,您选择了feature2
作为当前分支(通过git checkout feature2
)并创建了另一个提交:
...--F--G--H <-- origin/master
\
I--J--K <-- master
|\
| L--M <-- feature1
|
`--N <-- feature2 (HEAD)
出于任何无法解释的原因,您现在要执行的操作是使您的master
指向再次提交H
。通过告诉Git:移动master
,使其指向提交H
,可以对自己的存储库完全没有任何影响。效果是:
...--F--G--H <-- master, origin/master
\
I--J--K
|\
| L--M <-- feature1
|
`--N <-- feature2
提交I
至K
的方法如下:
feature1
的末尾开始并向后工作:M
,L
,K
,J
,I
,{{1 }},... H
的末尾开始,然后倒退:feature2
,N
,K
,J
,I
,... 您是否想记住提交H
的哈希ID作为专有名称,以便您可以从此处启动 new 功能,只需创建一个指向提交K
的新名称。这个新名称可以是分支名称或标签名称,以您喜欢的为准。
因此,我想将我的master分支还原为原来的未更改克隆master。而且,我想创建一个中间分支,其中包含我当前对主分支所做的更改。
您的K
最初指向的提交仍在您的存储库中。提交master
。当然,实际的提交哈希ID大而丑陋-并不是真正的H
,它是一些无法记住的长十六进制数字字符串。不幸的是:
同时,我想保留已经推送到远程存储库的功能分支。 (我也已经推送了修改后的master分支。)
运行H
时,您告诉Git发送提交git push origin master
,并在更早的时候将提交发送到K
(另一个Git存储库),然后询问管理{ 1}},将其主节点设置为指向origin
。接受此请求后,您的Git更新了您自己的origin
来记住哈希ID K
,而不是记住哈希ID origin/master
。因此,在这一点上,您会有更多类似的东西:
K
如果您还记得从H
开始倒数的确切次数 ,则可以找到...--F--G--H
\
I--J--K <-- master, origin/master
|\
| L--M <-- feature1
|
`--N <-- feature2
。但是,如果您最近(在过去三个月内)进行了所有这些操作,那么您自己的Git 仍会记得三个月或更短的时间K
指向的地方。这样就可以运行:
H
查看随着时间的推移,哪些origin/master
用于标识的提交。添加git reflog origin/master
以获取日期信息,您可能会发现日志回溯的时间远远超过了三个月。 Git清理它们的时间可能比较松懈,而且90天的有效期只是一个限制:当Git大力清理旧的reflog时,它将丢弃90天以上的东西(默认情况下,或丢弃30天以上的东西)有用的案例,不适用于此处。)
origin/master
因此要在您的存储库中找到--date=relative
,请尝试使用$ git reflog --date=relative origin/master
3c31a20 (HEAD -> master, origin/master) refs/remotes/origin/master@{51 minutes ago}: update by push
cf68824 refs/remotes/origin/master@{3 months ago}: update by push
...
ce4f7f9 refs/remotes/origin/master@{1 year, 2 months ago}: update by push
命令。
找到H
后,您可以为其附加新名称:
git reflog
将产生:
H
您现在可以使用这些不同的分支名称交换 git branch aha <hash-ID>
和...--F--G--H <-- aha
\
I--J--K <-- master, origin/master
|\
| L--M <-- feature1
|
`--N <-- feature2
(如果愿意)或进行其他操作。只要记住,如果有人 else 正在使用您的存储库或aha
存储库的克隆,那么这些其他人可能期望分支名称仅获取 new 提交。如果将分支名称“向后”移动(到较早的提交),其他人可能对此感到困惑,并试图坚持要求您再次将名称向前移动。