我有以下git历史记录,不确定我怎么到达那里,但是似乎我有一组DG副本(git diff D D-副本为空),这在git历史记录中创建了一个fork,解决此问题的方法,以删除副本并创建没有分叉的历史记录?
* b4c394e (HEAD -> master, origin/master) I
|\
| * 17738ee G-copy
| * 6300744 F-copy
| * 62dbb41 E-copy
| * 951a5d9 D-copy
* | 05bfe4f H
* | 2701442 G
* | 242cf72 F
* | 2c9c7b6 E
* | b4bf474 D
|/
* 0f445d1 C
* ac8114f B
* 87759e6 A
我有以下git历史记录,不太确定我是如何到达的...
[我预测/相信,您到了那里,通过使用git rebase
-可能是git rebase -i
的形式,如karan dhillon's answer-然后是git pull
。单独进行基线调整是可以的,但是您需要知道它的作用及其一些后果。
是否可以解决此问题,以删除副本并创建历史记录而无需使用分叉?
是,但是在此过程中,对[[other people产生了一些无关紧要,次要或可能相当重大的不愉快的后果……即,[[if origin
的任何其他用户涉及的存储库。
rebase -i
方法可以很好地工作(再次参见karan dhillon's answer,但很简单的方法很简单:git reset --hard HEAD~1
((但首先请确保使用git status
,您不介意替换索引和工作树中的所有文件,即git status
表示nothing to commit, working tree clean
)。用git log
检查结果以确保喜欢。
无论您如何获得所需的提交集,最后的关键步骤都是使用Git存储库。也就是说,最后,您git push --force
的变体来更新此处涉及的other
必须
指示另一个Git,即原点上方的一个,以丢弃某些其提交。 您的 Git拥有您的origin/master
(即原产地的master
的副本)这一事实意味着,在这一点上,他们也拥有所有这些提交(也许还有更多!)。如果其他人正在积极使用名称为origin
的Git记忆库中的Git记忆库正在被其他人积极使用,那么当您强制该共享的Git记忆库进行某些提交时,您需要警告它们。如果没有其他Git存储库的其他用户,例如,如果这是您自己的私有GitHub副本,则无需警告其他人,因此您可以在这里进行操作。一旦有了“正确的”历史记录,就需要运行:git push --force-with-lease origin master
git push --force origin master
(安全性较低,尤其是在源头上是共享存储库的情况下)。Git的-with-lease
变体使用您自己的Git的origin/master
(它对their
master
的记忆),以确保自您上次有机会查看并决定其Git的master
以来没有发生变化是的,您确实希望他们忘记their提交。
很多细节
让我们在这里再次查看历史:* b4c394e (HEAD -> master, origin/master) I
|\
| * 17738ee G-copy
| * 6300744 F-copy
| * 62dbb41 E-copy
| * 951a5d9 D-copy
* | 05bfe4f H
* | 2701442 G
* | 242cf72 F
* | 2c9c7b6 E
* | b4bf474 D
|/
* 0f445d1 C
* ac8114f B
* 87759e6 A
git log --graph
的一个不错的特性是它通过将第一个父级绘制为下面的直接垂直线来显示提交的第一对第二个父级,即b4c394e
的first父级(合并提交)为05bfe4f
(提交H
)。
second是
17738ee
(G副本)。[这向我表明,您实际上已经或曾经提交过951a5d9
(在这里称为D-copy),62dbb41
,6300744
和17738ee
(先后顺序),然后发送通过origin
将它们传递到git push
处的另一个Git,或者将它们从origin
处的另一个Git获得。但是您可能不喜欢原始提交D
,您将其称为D-copy
。也许就像提交消息中的错字一样简单。无论出于什么原因,您都使用了一个提交(可能是git rebase
)来告诉您的
我不喜欢951a5d9
然后62dbb41
然后6300744
然后17738ee
,我想而是提取951a5d9,对其进行一些更改,然后制作一个新的和改进的副本。
此新的经过改进的副本原来是b4bf474
:您现在调用的提交D
。 Rebase会自动复制所有后续提交,因为它必须执行以下操作:调用E-copy
的原始E
的副本必须使用b4bf474
作为其父项,因此它必须是已更改的副本。新的提交最终为2c9c7b6
。出于相同的原因,必须将要调用F-copy的提交复制到要调用F的提交,依此类推。最后,您依次有四个新的和改进的提交,以b4bf474
开头,以2701442
结束。这些新的和改进的副本都不存在于origin
的其他Git存储库中。它仍然以17738ee
作为其最后的master
提交。您自己的Git已丢弃您的原件(您称其为副本的原件),因为新的和改进的副本(您称其为原件的副本)是经过改进的。
H
,这是全新的。然后,您使用origin
将您的新提交(新的和经过改进的提交,然后是全新的提交)发送到git push origin master
处的Git。但是无论出于什么原因,您都在git pull
成功之前运行了git push origin master
。((如果您运行了git push origin master
之前
,您运行了git pull
,则另一个Git在origin
处表示否。更具体地说,您的Git向他们发送了五个新提交,即D
- -H
,并要求他们更改名称master
来记住H
作为their
分支上的最后一次提交,他们注意到这将丢弃D-copy
-through- G-copy
。说不,我会丢失一些提交
,它作为rejected (non-fast-forward)
错误消息出现,并提示您使用git pull
。)不幸的是,git pull
的意思是运行git fetch
,然后根据获取的内容运行git merge
。提取操作获取了他们的master
,这时仍然标识为提交17738ee
。然后您的Git做了:git merge -m "merge branch master of <url>" 17738ee
(或多或少),它创建了合并提交b4c394e
(commit I
),您可以在git log
输出的顶部看到它。合并(合并)的提交将提交05bfe4f
和17738ee
。然后您运行:
git push origin master
[这次,您向他们发送了尚未通过的提交,包括I
(不仅仅是H
),并要求他们将master
设置为指向提交I
。他们没关系:确实丢失了提交17738ee
,因为从b4c394e
开始并向后工作,他们仍然可以找到提交17738ee
:它是b4c394e
的第二父级。但是您要做的最终是创建一些以提交
H
结尾的提交字符串,即,您现在拥有的哈希ID或提交的一些经过改进的新副本[ C0](即,一些不同的哈希ID:哈希ID是提交的real名称;主题和消息只是实际提交中的数据)。然后,您的分支名称H
指向此最后一次提交(存储其的哈希ID)。提交本身存储了先前提交的哈希ID,也将其视为包含在master
分支中。上一次提交包含下一次提交的哈希ID,依此类推。
一旦您的master
具有正确的哈希ID,您将使用master
将您拥有但没有的任何新提交通过名称为git push
的URL发送到另一个Git。该提交字符串以提交origin
或新改进的替换结尾。然后,您需要order
their
05bfe4f
,使其拥有与your master
相同的哈希ID。这是master
步骤。如果使用简单的(并且更旧的)git push --force
,则Git只会发送一条命令:设置您的git push --force
!如果您使用较新的(但现在非常标准)master
,则您的Git发送了一个更复杂的命令:我认为您的git push --force-with-lease
是______。如果是这样,请将您的主服务器设置为_____。告诉我是否更新master
。您的Git用适当的哈希ID填充这些空白。
master
,要么告诉您失败,但没有成功。如果是因为哈希值不匹配,则它们的origin/master
已更改,您应该运行master
更新您的git fetch
,然后查看到底发生了什么。 在控制台中输入:
origin/master