确定,我有一个git奇怪的问题(使用BitBucket。)。
我有以下(示例)
development-branch
child-branch
现在在[[child-branch
中,我做了很多重做,但在同一时期,我也进行了一些错误修正,其中该错误是通过development-branch
中另一个子分支的拉取请求合并而成的。现在,当我从child-branch
向development-branch
发出拉取请求时,它想删除对[[development-branch
所做的修复。但是,当我想在development-branch
中合并child-branch
时,对[[development-branch
所做的修订不会合并到child-branch
。
每个人使用重新创建的分支必须准备放弃旧的提交。
长Branches,或更确切地说,分支names
没有父子关系。分支名称只是标签,附加到(或指向)特定的[[commits。
Commits,但是,do具有父/子关系。特别是,用于执行new提交的命令序列如下所示:
git checkout somebranch
[edit various files]
git add file1.ext file2.ext
git commit
git checkout
步骤的意思是选择命名的分支,然后选择分支名称选择的提交。该提交的复制内容(在Git中是所有文件的完整快照,以特殊的,只读的,仅Git的压缩格式存储)到index
中aka
临时区域和工作树或工作树。1
当然,编辑步骤适用于工作树中的那些文件。git add
步骤复制已更新的工作树文件(在其中进行了更改)<< [返回到索引/暂存区,最后一步git commit
创建新快照,使用从索引中的副本中获取其文件的永久冻结副本。您用git add
覆盖的所有文件仍然与您以前的git checkout
覆盖的文件相同,因此新快照包含所有[[arn't更改并更新的文件。 are已更改的文件,视情况而定。但是,新提交是先前标记的提交的子
。先前的提交未更改-提交后,即使Git本身也无法更改任何内容-但现在具有子提交。刚刚完成的子提交记录了其parent提交的原始哈希ID。因此,从孩子到父母的联系只有一种向后的方式。由于子项是新提交,因此它将获得新的唯一哈希ID。git commit
的最后一个关键步骤是它将新的提交哈希ID写入分支名称] >>。也就是说,标签停止指向先前的父提交,而现在指向子提交。
... <-F <-G <-H <-- develop
<< [名称
develop
当前选择提交H
。为此,您添加了一个新名称feature
,该名称还选择了提交H
:...--F--G--H <-- develop, feature
您正在使用的分支名称
。为此,我们将特殊名称HEAD
附加到一个分支。如果您git checkout develop
,我们会将名称HEAD
附加到develop
:...--F--G--H <-- develop (HEAD), feature
如果您git checkout feature
,我们得到:
...--F--G--H <-- develop, feature (HEAD)
不管哪种方式,您都是using
提交H
,但是您通过附加到/的两个名称之一来指向H
。 (同时,提交H
指向以提交G
作为其父级,而G
指向回F
,依此类推。)]现在您修改工作树中的某些文件,git add
将其复制回索引/暂存区,然后单击git commit
进行新提交I
。如果您使用的是feature
,则会发生以下情况:
...--F--G--H <-- develop
\
I <-- feature (HEAD)
HEAD
仍附加在名称feature
上,但是feature
现在指向新的提交I
。新提交I
指向提交H
-前一时刻feature
指向-feature
包含直到I
为止的提交,并且develop
包含直到H
处的提交。 。注意大多数提交仍然在两个分支上。如果并且当您将提交添加到develop
时,它们只会添加到develop
:
...--F--G--H--K <-- develop (HEAD) \ I--J <-- feature
名称develop
和feature
之间没有父/子关系。它们只是labels
,用于标识特定的提交。这是Git中分支和标记名称的工作方式:它们标识提交。分支名称和标记名称之间的区别是:
随着时间的流逝。实际上,它们会自动移动!标记名称永远不能移动。分支名称
移动
2
分支名称是 在一个特定存储库中本地
master
)复制到您的origin/master
) 。标记名称更具全局性:如果它们(无论它们是什么)具有v1.2
,而您从它们中获得提交,则Git可能会创建要匹配的v1.2
。3当然,分支名称是
tag名称:有很多较小的连锁效果,但以上两点是重要的区别。
2
3
这在您的控制之下,这里的默认规则有些复杂,但是如果您没有做任何特别的事情,它们就等于您可以获取其标签。使用变基假设您有这个:...--F--G--H--K <-- develop
\
I--J <-- feature (HEAD)
?--? <-- feature (HEAD)
/
...--F--G--H--K <-- develop
您无法更改现有提交。没办法现有提交I
和J
被卡在原处。但是您can
I
复制到新的改进的提交中-我们将其称为I'
表示它是I
的副本,尽管在Git中它只是看起来有些笨拙,看起来很丑陋与I
的哈希ID无关的哈希ID。 I
和I'
之间的差异为:[I
的父母是H
,但是I'
的父母将是K
。
将与通过比较I
的快照和I'
的快照可能不匹配,但是通过比较H
-vs-I
获得的difference
K
-vs- I'
获得的差异。
将I
复制到I'
之后,我们希望Git将J
复制到J'
。结果看起来像这样: I'-J'
/
...--F--G--H--K <-- develop
\
I--J
[请注意,我已经删除了标签feature
,并完全省略了名称HEAD
,因为在这一点上,我们准备移动feature
,并将HEAD
附加到新移动的[ C0]。执行此“构建新提交”的过程实际上使用了Git所说的detached HEAD,因此,现在的实际情况是:
feature
I'-J' <-- HEAD
/
...--F--G--H--K <-- develop
\
I--J <-- feature
HEAD
仍会选择现有提交feature
。J
命令的最后一步,是完成基准,是从现有提交(git rebase
)剥离名称feature
,并使其指向与J
指向的同一提交(HEAD
):J'
已移动标签,将 I'-J' <-- feature, HEAD
/
...--F--G--H--K <-- develop
\
I--J [abandoned]
重新固定到已移动的标签上,使所有内容看起来都像我们想要的样子。而且,由于Git
finds提交的方式是从
labels
开始并向后工作,因此我们不能see再次提交HEAD
和I
。我们所看到的是:我们的new。J
如果我们不记得提交
I'-J' <-- feature (HEAD) / ...--F--G--H--K <-- develop
和I
的哈希ID,我们会认为Git以某种方式移动了旧的提交。它没有—旧提交仍然存在,并且拥有存储库克隆并拥有旧提交的每个人仍然拥有旧提交。不过,我们仅see
[如Nikos C.所述,如果您有一个使用现有提交J
的活动拉取请求,则可能需要使用I-J
更新拉取请求。您必须获得Git存储库保存其提交git push --force
和I
的副本的任何内容,以放弃它们的提交,而使用新的和改进的J
链。说服其他Git从旧提交切换到新提交的精确方法取决于设置其他Git的控件。 GitHub允许简单的I'-J'
完成技巧。